public void OneImageToRuleThemAll(ImageFile im, string archiveDir, byte[] imgData) { ImageMipMapHandler imgMipMap = new ImageMipMapHandler("", imgData); // starts from the smaller image for (int i = imgMipMap.imageList.Count - 1; i >= 0; i--) { ImageFile newImageFile = imgMipMap.imageList[i]; if (newImageFile.imgSize.height < 4 || newImageFile.imgSize.width < 4) continue; ImageEngineFormat newImageFileFormat = Textures.Methods.ParseFormat(newImageFile.format); //NEW Check for correct format if (texFormat != newImageFileFormat) { //MessageBox.Show("Warning! The input image is of the wrong format! Aborting"); throw new FormatException("Different image format, original is " + texFormat + ", new is " + newImageFile.subtype()); } // if the image size exists inside the texture2d image list then we have to replace it if (privateimgList.Exists(img => img.imgSize == newImageFile.imgSize)) { // ...but at least for now I can reuse my replaceImage function... ;) replaceImage(newImageFile.imgSize.ToString(), newImageFile, archiveDir); } else // if the image doesn't exists then we have to add it { // ...and use my addBiggerImage function! :P addBiggerImage(newImageFile, archiveDir); } } while (privateimgList[0].imgSize.width > imgMipMap.imageList[0].imgSize.width) { privateimgList.RemoveAt(0); numMipMaps--; if (properties.ContainsKey("MipTailBaseIdx")) properties["MipTailBaseIdx"].Value.IntValue--; } if (properties.ContainsKey("SizeX")) properties["SizeX"].Value.IntValue = (int)imgMipMap.imageList[0].imgSize.width; if (properties.ContainsKey("SizeY")) properties["SizeY"].Value.IntValue = (int)imgMipMap.imageList[0].imgSize.height; }
public void OneImageToRuleThemAll(ImageFile im, string archiveDir, byte[] imgData) { ImageMipMapHandler imgMipMap = new ImageMipMapHandler("", imgData); if (Class == class2 || Class == class3) ChangeFormat(imgMipMap.imageList[0].format); // starts from the smaller image for (int i = imgMipMap.imageList.Count - 1; i >= 0; i--) { ImageFile newImageFile = imgMipMap.imageList[i]; if (!Methods.CheckTextureFormat(texFormat, newImageFile.format)) throw new FormatException("Different image format, original is " + texFormat + ", new is " + newImageFile.subtype()); // if the image size exists inside the texture2d image list then we have to replace it if (privateimgList.Exists(img => img.imgSize == newImageFile.imgSize)) { // ...but at least for now I can reuse my replaceImage function... ;) replaceImage(newImageFile.imgSize.ToString(), newImageFile, archiveDir); } else if (newImageFile.imgSize.width > privateimgList[0].imgSize.width) // if the image doesn't exists then we have to add it { // ...and use my addBiggerImage function! :P addBiggerImage(newImageFile, archiveDir); } //else // addMissingImage(newImageFile.imgSize.ToString(), newImageFile.fileName); // else ignore the image } // Remove higher res versions and fix up properties while (privateimgList[0].imgSize.width > imgMipMap.imageList[0].imgSize.width) //while (imgMipMap.imageList.Count + 2 < imgList.Count) { privateimgList.RemoveAt(0); numMipMaps--; } if (properties.ContainsKey("SizeX")) properties["SizeX"].Value.IntValue = (int)privateimgList[0].imgSize.width; if (properties.ContainsKey("SizeY")) properties["SizeY"].Value.IntValue = (int)privateimgList[0].imgSize.height; if (properties.ContainsKey("MipTailBaseIdx")) properties["MipTailBaseIdx"].Value.IntValue = privateimgList.Count + 1; }
public void OneImageToRuleThemAll(string imageFileName, string archiveDir, out string newTextureGroup) { newTextureGroup = null; ImageMipMapHandler imgMipMap = new ImageMipMapHandler(imageFileName, null); // starts from the smaller image for (int i = imgMipMap.imageList.Count - 1; i >= 0; i--) { ImageFile newImageFile = imgMipMap.imageList[i]; // insert images only with size > 64 if (newImageFile.imgSize.width < 64 && newImageFile.imgSize.height < 64) continue; // write the new image into a file (I know that's crappy solution, I'll find another one later...) using (FileStream newImageStream = File.Create(newImageFile.fileName)) { byte[] buffer = newImageFile.ToArray(); newImageStream.Write(buffer, 0, buffer.Length); } // if the image size exists inside the texture2d image list then we have to replace it if (imgList.Exists(img => img.imgSize == newImageFile.imgSize)) { // ...but at least for now I can reuse my replaceImage function... ;) replaceImage(newImageFile.imgSize.ToString(), newImageFile.fileName, archiveDir); } else // if the image doesn't exists then we have to add it { // ...and use my addBiggerImage function! :P addBiggerImage(newImageFile.fileName, archiveDir); } File.Delete(newImageFile.fileName); } // check that Texture2D has a TextureGroup if (!properties.ContainsKey("LODGroup")) return; // extracting values from LODGroup Property PropertyReader.Property LODGroup = properties["LODGroup"]; string textureGroupName = pccRef.Names[LODGroup.Value.IntValue]; string newTextureGroupName = "TEXTUREGROUP_Shadowmap"; textureGroupName = newTextureGroupName; int nameIndex = pccRef.FindNameOrAdd(newTextureGroupName); using (MemoryStream rawStream = new MemoryStream(LODGroup.raw)) { rawStream.Seek(32, SeekOrigin.Begin); rawStream.WriteValueS32(nameIndex); //rawStream.Seek(32, SeekOrigin.Begin); rawStream.WriteValueS32(0); properties["LODGroup"].raw = rawStream.ToArray(); } //LODGroup.Value.IntValue = pccRef.Names.FindIndex(name => name == newTextureGroupName); /*MessageBox.Show("Texturegroup Name: " + textureGroupName); ImageSize maxImageSize = imgList.Max(image => image.imgSize); int textureGroupValue = (int)Math.Max(maxImageSize.width, maxImageSize.height) + 1; // open Engine.pcc file and edit TextureGroup enumerator { PCCObject pccEngine = new PCCObject(ME3Directory.cookedPath + "Engine.pcc"); int idxTexGroups = pccEngine.Exports.FindIndex(export => export.ObjectName == "TextureGroup"); TextureGroup texGroup = new TextureGroup(pccEngine, pccEngine.Exports[idxTexGroups].Data); if (texGroup.ExistsTextureGroup(textureGroupName, textureGroupValue)) return; else { if (!pccEngine.Names.Exists(name => name == newTextureGroupName)) pccEngine.Names.Add(newTextureGroupName); newTextureGroup = textureGroupName + "_" + (textureGroupValue - 1); texGroup.Add(textureGroupName, textureGroupValue); MessageBox.Show("Now editing texgroup enum"); pccEngine.Exports[idxTexGroups].Data = texGroup.ToArray(); MessageBox.Show("Now saving engine.pcc"); pccEngine.saveToFile(true, ME3Directory.cookedPath + "Engine.pcc"); MessageBox.Show("Saved engine.pcc"); } }*/ }
public void OneImageToRuleThemAll(string imageFileName) { ImageMipMapHandler imgMipMap = new ImageMipMapHandler(imageFileName, null); if (Class == class2 || Class == class3) ChangeFormat(imgMipMap.imageList[0].format); // starts from the smaller image for (int i = imgMipMap.imageList.Count - 1; i >= 0; i--) { ImageFile newImageFile = imgMipMap.imageList[i]; if (texFormat != newImageFile.format && texFormat != "PF_" + newImageFile.format && newImageFile.format != "ATI2") throw new FormatException("Different image format, original is " + texFormat + ", new is " + newImageFile.subtype()); // write the new image into a file (I know that's crappy solution, I'll find another one later...) using (FileStream newImageStream = File.Create(newImageFile.fileName)) { byte[] buffer = newImageFile.ToArray(); newImageStream.Write(buffer, 0, buffer.Length); } // if the image size exists inside the texture2d image list then we have to replace it if (imgList.Exists(img => img.imgSize == newImageFile.imgSize)) { // ...but at least for now I can reuse my replaceImage function... ;) replaceImage(newImageFile.imgSize.ToString(), newImageFile.fileName); } else if (newImageFile.imgSize.width > imgList[0].imgSize.width) // if the image doesn't exists then we have to add it { // ...and use my addBiggerImage function! :P addBiggerImage(newImageFile.fileName); } // else ignore the image File.Delete(newImageFile.fileName); } // Remove higher res versions and fix up properties while (imgList[0].imgSize.width > imgMipMap.imageList[0].imgSize.width) { imgList.RemoveAt(0); numMipMaps--; } if (properties.ContainsKey("SizeX")) properties["SizeX"].Value.IntValue = (int)imgList[0].imgSize.width; if (properties.ContainsKey("SizeY")) properties["SizeY"].Value.IntValue = (int)imgList[0].imgSize.height; if (properties.ContainsKey("MipTailBaseIdx")) properties["MipTailBaseIdx"].Value.IntValue = imgList.Count + 1; }
// New methods! public void OneSizeFitsAll(String inputFile, bool resFix = false) { // forced lowresfix // resFix = true; if (!File.Exists(inputFile)) throw new FileNotFoundException("Input texture not found at: " + inputFile); bool containsmips = true; ImageMipMapHandler mipmaps = null; if (imgList.Count > 1) { try{ mipmaps = new ImageMipMapHandler(inputFile, null); } catch (FormatException) { containsmips = false; } } else containsmips = false; ImageInfo existingImg = imgList.First(img => img.storageType != storage.empty); if (containsmips) { if ((float)mipmaps.imageList[0].imgSize.width / (float)mipmaps.imageList[0].imgSize.height != (float)existingImg.imgSize.width / (float)existingImg.imgSize.height) throw new FormatException("Input texture not correct aspect ratio"); if (mipmaps.imageList[0].format == "PF_R8G8B8") // Convert to 32-bit if necessary { for (int i = 0; i < mipmaps.imageList.Count; i++) mipmaps.imageList[i] = new DDS(null, mipmaps.imageList[i].imgSize, "A8R8G8B8", ImageMipMapHandler.ConvertTo32bit(mipmaps.imageList[i].resize(), (int)mipmaps.imageList[i].imgSize.width, (int)mipmaps.imageList[i].imgSize.height)); } if (Class == class2 || Class == class3) // Allow format modification if one of the derived classes. Don't need the single level check since we're replacing all levels ChangeFormat(mipmaps.imageList[0].format); if (texFormat == "PF_NormalMap_HQ") // Check formats { if (mipmaps.imageList[0].format != "ATI2") throw new FormatException("Texture not in correct format - Expected ATI2"); } else if (String.Compare(texFormat, "PF_" + mipmaps.imageList[0].format, true) != 0) throw new FormatException("Texture not in correct format - Expected " + texFormat); for (int i = mipmaps.imageList.Count - 1; i >= 0; i--) { if (imgList.Exists(img => img.imgSize == mipmaps.imageList[i].imgSize)) ReplaceImage(mipmaps.imageList[i]); else if (mipmaps.imageList[i].imgSize.width > imgList.First().imgSize.width && mipmaps.imageList[i].imgSize.height > imgList.First().imgSize.height) UpscaleImage(mipmaps.imageList[i]); //else // AddMissingImage(mipmaps.imageList[i]); // Else ignore missing values } while (imgList[0].imgSize.width > mipmaps.imageList[0].imgSize.width) // Remove any existing higher levels imgList.RemoveAt(0); } else { ImageFile ddsfile = new DDS(inputFile, null); if ((float)ddsfile.imgSize.width / (float)ddsfile.imgSize.height != (float)existingImg.imgSize.width / (float)existingImg.imgSize.height) // Check dimensions throw new FormatException("Input texture not correct aspect ratio"); if (ddsfile.format == "R8G8B8") ddsfile = new DDS(null, ddsfile.imgSize, "A8R8G8B8", ImageMipMapHandler.ConvertTo32bit(ddsfile.resize(), (int)ddsfile.imgSize.width, (int)ddsfile.imgSize.height)); if (imgList.Count == 1 && (Class == class2 || Class == class3)) // Since this is single level replacement, only allow format change if a single level texture with required class ChangeFormat(ddsfile.format); if (texFormat == "PF_NormalMap_HQ") // Check format { if (ddsfile.format != "ATI2") throw new FormatException("Texture not in correct format - Expected ATI2"); } else if (String.Compare(texFormat, "PF_" + ddsfile.format, true) != 0) throw new FormatException("Texture not in correct format - Expected " + texFormat); if (imgList.Count == 1 && imgList[0].imgSize != ddsfile.imgSize) // If img doesn't exist and it's a single level texture, use hard replace HardReplaceImage(ddsfile); else if (imgList.Exists(img => img.imgSize == ddsfile.imgSize)) // Catches the rest of the single levels and every one which has an existing reference for that level ReplaceImage(ddsfile); else if (ddsfile.imgSize.width > imgList[0].imgSize.width) // Add a greater image UpscaleImage(ddsfile); //else if (ddsfile.imgSize.width < imgList.Last().imgSize.width) // Add a smaller image // AddMissingImage(ddsfile); } if (imgList.Count > 1 && resFix) LowResFix(); // Fix up properties if (properties.ContainsKey("SizeX")) properties["SizeX"].Value.IntValue = (int)imgList.First(img => img.storageType != storage.empty).imgSize.width; if (properties.ContainsKey("SizeY")) properties["SizeY"].Value.IntValue = (int)imgList.First(img => img.storageType != storage.empty).imgSize.height; if (properties.ContainsKey("MipTailBaseIdx")) properties["MipTailBaseIdx"].Value.IntValue = imgList.Count - 1; numMipMaps = (uint)imgList.Count; }
public void OneImageToRuleThemAll(string archiveDir, ImageFile im, out string newTextureGroup, byte[] imgData) { newTextureGroup = null; ImageMipMapHandler imgMipMap = new ImageMipMapHandler("", imgData); // starts from the smaller image for (int i = imgMipMap.imageList.Count - 1; i >= 0; i--) { ImageFile newImageFile = imgMipMap.imageList[i]; // insert images only with size > 64 if (newImageFile.imgSize.width < 64 && newImageFile.imgSize.height < 64) continue; // if the image size exists inside the texture2d image list then we have to replace it if (imgList.Exists(img => img.imgSize == newImageFile.imgSize)) { // ...but at least for now I can reuse my replaceImage function... ;) replaceImage(newImageFile.imgSize.ToString(), newImageFile, archiveDir); } else // if the image doesn't exists then we have to add it { // ...and use my addBiggerImage function! :P addBiggerImage(newImageFile, archiveDir); } File.Delete(newImageFile.fileName); } // add texturegroup_world inside GamerSettings.ini in order to overwrite values ImageSize maxSize = imgList.Max(image => image.imgSize); uint maxValue = Math.Max(maxSize.width, maxSize.height); string section = "SystemSettings"; string key = "texturegroup_shadowmap"; string newValue = "(MinLODSize=128,MaxLODSize=" + maxValue + ",LODBias=0)"; IniFile iniFile = new IniFile(ME3Directory.GamerSettingsIniFile); string oldValue = iniFile.IniReadValue(section, key); if (oldValue == "") { iniFile.IniWriteValue(section, key, newValue); } else { char[] delimiters = new char[] { '=', ',' }; uint maxLODSize = Convert.ToUInt32(oldValue.Split(delimiters)[3]); if (maxValue > maxLODSize) iniFile.IniWriteValue(section, key, newValue); } // check that Texture2D has a TextureGroup if (!properties.ContainsKey("LODGroup")) return; // extracting values from LODGroup Property PropertyReader.Property LODGroup = properties["LODGroup"]; string textureGroupName = pccRef.Names[LODGroup.Value.IntValue]; string newTextureGroupName = "TEXTUREGROUP_Shadowmap"; textureGroupName = newTextureGroupName; if (!pccRef.Names.Exists(name => name == newTextureGroupName)) pccRef.Names.Add(newTextureGroupName); using (MemoryStream rawStream = new MemoryStream(LODGroup.raw)) { rawStream.Seek(32, SeekOrigin.Begin); rawStream.WriteValueS32(pccRef.Names.FindIndex(name => name == newTextureGroupName)); //rawStream.Seek(32, SeekOrigin.Begin); rawStream.WriteValueS32(0); properties["LODGroup"].raw = rawStream.ToArray(); } }
private void ReplaceButton_Click(object sender, EventArgs e) { if (MainListView.SelectedIndices.Count != 0 && MainListView.SelectedIndices[0] >= 0) { // KFreon: Select mip to replace List<string> names = new List<string>(); int index = GetSelectedTexInd(); TreeTexInfo tex = Tree.GetTex(index); Textures.ITexture2D tex2D = tex.Textures[0]; for (int i = 0; i < tex2D.imgList.Count; i++) { bool pccstored = tex2D.imgList[i].CompareStorage("pccSto"); names.Add("Image: " + tex2D.imgList[i].imgSize + " stored inside " + (pccstored ? "PCC file" : "Archive file") + " at offset " + ((pccstored) ? (tex2D.imgList[i].offset + tex2D.pccOffset).ToString() : tex2D.imgList[i].offset.ToString())); } string selectedImage = ""; using (Helpers.SelectionForm sf = new Helpers.SelectionForm(names, "Select ONE image to replace.", "Replace Image Selector", false)) { sf.ShowDialog(); if (sf.SelectedInds.Count == 0) return; else if (sf.SelectedInds.Count == 1) selectedImage = sf.SelectedItems[0]; else { MessageBox.Show("You must select ONLY ONE image to replace."); return; } } string imgsize = selectedImage.Split(' ')[1]; string replacingfile = ""; using (OpenFileDialog ofd = new OpenFileDialog()) { ofd.Title = "Select Image to replace with"; ofd.Filter = "Image File|*.dds"; if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK) replacingfile = ofd.FileName; else return; } byte[] imgData = File.ReadAllBytes(replacingfile); ImageMipMapHandler mip = new ImageMipMapHandler("", imgData); string[] sizes = imgsize.Split('x'); ImageFile im = mip.imageList.First(img => img.imgSize.width.ToString() == sizes[0] && img.imgSize.height.ToString() == sizes[1]); DebugOutput.PrintLn("Replacing image in " + tex.TexName + " at " + imgsize + " with " + replacingfile); tex2D.replaceImage(imgsize, im, pathBIOGame); UpdateModifiedTex(tex2D, tex, index); DebugOutput.PrintLn("Image replaced."); StatusUpdater.UpdateText("Image replaced!"); MainProgressBar.Value = MainProgressBar.Maximum; DisplayTextureProperties(tex2D, tex2D.GenerateImageInfo()); RegenerateThumbnail(tex, index, false); if (ModMakerMode) { AddModJob(tex2D, replacingfile); StatusUpdater.UpdateText("Replacement complete and job added to modmaker!"); } if (TPFMode) { AddTPFToolsJob(replacingfile, tex.Hash); StatusUpdater.UpdateText("Replacement Complete and job added to TPFTools!"); } } }
public void InstallTexture(string texname, List<string> pccs, List<int> IDs, byte[] imgdata) { string fulpath = pccs[0]; string temppath = (WhichGame == 1) ? Path.GetDirectoryName(pathBIOGame) : pathBIOGame; if (!fulpath.Contains(temppath)) fulpath = Path.Combine(temppath, fulpath); // KFreon: Skip files that don't exist if (!File.Exists(fulpath)) return; PCCObjects.IPCCObject pcc = PCCObjects.Creation.CreatePCCObject(fulpath, WhichGame); if ((pcc.Exports[IDs[0]].ClassName != "Texture2D" && pcc.Exports[IDs[0]].ClassName != "LightMapTexture2D" && pcc.Exports[IDs[0]].ClassName != "TextureFlipBook") || String.Compare(pcc.Exports[IDs[0]].ObjectName, texname, true) != 0) throw new InvalidDataException("Export is not correct class or name!"); //Load the texture from the pcc Textures.ITexture2D tex2D = null; tex2D = pcc.CreateTexture2D(IDs[0], pathBIOGame); tex2D.allPccs = pccs; tex2D.expIDs = IDs; int noImg = tex2D.imgList.Count; DebugOutput.PrintLn("Now replacing textures in texture: " + tex2D.texName, true); Debug.WriteLine("Now replacing textures in texture: " + tex2D.texName + " ID: " + IDs[0]); WriteDebug("Now replacing textures in texture: " + tex2D.texName + " ID: " + IDs[0]); ImageFile im = null; try { im = new DDS("", imgdata); } catch { Console.WriteLine(""); } // KFreon: TESTING Debug.WriteLine("First pcc: " + fulpath + " ArcName: " + tex2D.arcName); WriteDebug("First pcc: " + fulpath + " ArcName: " + tex2D.arcName); //The texture is a single image, therefore use replace function if (noImg == 1) { string imgSize = tex2D.imgList[0].imgSize.width.ToString() + "x" + tex2D.imgList[0].imgSize.height.ToString(); try { tex2D.replaceImage(imgSize, im, pathBIOGame); } catch { // KFreon: If replace fails, it's single image thus use the singleimageupscale function tex2D.singleImageUpscale(im, pathBIOGame); } } //If the texture has multiple images, then check the input texture for MIPMAPS else { bool hasMips = true; ImageFile imgFile = im; try { ImageMipMapHandler imgMipMap = new ImageMipMapHandler("", imgdata); } catch { hasMips = false; } if (!hasMips) { //string fileformat = Path.GetExtension(texFile); //imgFile = new DDS(texFile); string imgSize = imgFile.imgSize.width.ToString() + "x" + imgFile.imgSize.height.ToString(); try { //Try replacing the image. If it doesn't exist then it'll throw and error and you'll need to upscale the image tex2D.replaceImage(imgSize, imgFile, pathBIOGame); } catch { tex2D.addBiggerImage(imgFile, pathBIOGame); } } else { try { tex2D.OneImageToRuleThemAll(imgFile, pathBIOGame, imgdata); } catch (Exception e) { if (e.Message.Contains("Format")) { MessageBox.Show(texname + " is in the wrong format." + Environment.NewLine + Environment.NewLine + e.Message); return; } } } } Debug.WriteLine("After replace: " + tex2D.arcName); WriteDebug("After replace: " + tex2D.arcName); DebugOutput.PrintLn("Replacement complete. Now saving pcc: " + pcc.pccFileName, true); //tex2D.DumpTexture(@"R:\commit.txt"); PCCObjects.IExportEntry expEntry = pcc.Exports[IDs[0]]; expEntry.SetData(tex2D.ToArray(expEntry.DataOffset, pcc)); expEntry.hasChanged = true; pcc.Exports[IDs[0]] = expEntry; pcc.saveToFile(pcc.pccFileName); /*File.Delete(loc + "tex.dds"); File.Delete(loc + "data.bin");*/ int modCount = tex2D.allPccs.Count; // KFreon: Elapsed time stuff int start = Environment.TickCount; // KFreon: Start threading of save function (max 10 threads) //ParallelOptions po = new ParallelOptions(); //po.MaxDegreeOfParallelism = 2; if (modCount > 1) //Parallel.For(1, modCount, po, (item, loopstate) => for (int item = 1; item < modCount; item++) { Debug.WriteLine(pccs[item] + " " + IDs[item]); WriteDebug(pccs[item] + " " + IDs[item]); if (!SaveFile(pccs, IDs, tex2D, item)) break; /*loopstate.Stop(); });*/ } Debug.WriteLine(""); WriteDebug(""); // KFreon: More timer stuff TimeSpan ts = TimeSpan.FromMilliseconds(Environment.TickCount - start); Console.WriteLine(ts.Duration().ToString()); GC.Collect(); DebugOutput.Print("All PCC updates finished. "); }