// 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 singleImageUpscale(string imagePathToAdd, string archiveDir) { ImageSize biggerImageSizeOnList = imgList.Max(image => image.imgSize); // check if replacing image is supported ImageFile imgFile; string fileFormat = Path.GetExtension(imagePathToAdd); switch (fileFormat) { case ".dds": imgFile = new DDS(imagePathToAdd, null); break; case ".DDS": imgFile = new DDS(imagePathToAdd, null); break; default: throw new FormatException(fileFormat + " image extension not supported"); } if (texFormat == "PF_NormalMap_HQ") { if (imgFile.format != "ATI2") throw new FormatException("Different image format, original is " + texFormat + ", new is " + imgFile.subtype()); } else if (String.Compare(texFormat, "PF_" + imgFile.format, true) != 0 && String.Compare(texFormat, imgFile.format, true) != 0) { throw new FormatException("Different image format, original is " + texFormat + ", new is " + imgFile.subtype()); } // !!! warning, this method breaks consistency between imgList and imageData[] !!! ImageInfo newImgInfo = new ImageInfo(); newImgInfo.storageType = imgList.Find(img => img.storageType != storage.empty && img.storageType != storage.pccSto).storageType; newImgInfo.imgSize = imgFile.imgSize; newImgInfo.uncSize = imgFile.resize().Length; newImgInfo.cprSize = 0x00; // not yet filled newImgInfo.offset = 0x00; // not yet filled imgList.RemoveAt(0); // Remove old single image and add new one imgList.Add(newImgInfo); //now I let believe the program that I'm doing an image replace, saving lot of code ;) replaceImage2(newImgInfo.imgSize.ToString(), imagePathToAdd, archiveDir); // update Sizes properties["SizeX"].Value.IntValue = (int)newImgInfo.imgSize.width; properties["SizeY"].Value.IntValue = (int)newImgInfo.imgSize.height; }
public void replaceImage2(string strImgSize, string fileToReplace, string archiveDir) { ImageSize imgSize = ImageSize.stringToSize(strImgSize); if (!imgList.Exists(img => img.imgSize == imgSize)) throw new FileNotFoundException("Image with resolution " + imgSize + " isn't found"); int imageIdx = imgList.FindIndex(img => img.imgSize == imgSize); ImageInfo imgInfo = imgList[imageIdx]; if (!File.Exists(fileToReplace)) throw new FileNotFoundException("invalid file to replace: " + fileToReplace); // check if replacing image is supported ImageFile imgFile; string fileFormat = Path.GetExtension(fileToReplace); switch (fileFormat) { case ".dds": imgFile = new DDS(fileToReplace, null); break; case ".DDS": imgFile = new DDS(fileToReplace, null); break; default: throw new FormatException(fileFormat + " image extension not supported"); } if (texFormat == "PF_NormalMap_HQ") { if (imgFile.format != "ATI2") throw new FormatException("Different image format, original is " + texFormat + ", new is " + imgFile.subtype()); } else if (String.Compare(texFormat, "PF_" + imgFile.format, true) != 0 && String.Compare(texFormat, imgFile.format, true) != 0) { throw new FormatException("Different image format, original is " + texFormat + ", new is " + imgFile.subtype()); } byte[] imgBuffer; // if the image is empty then recover the archive compression from the image list if (imgInfo.storageType == storage.empty) { imgInfo.storageType = imgList.Find(img => img.storageType != storage.empty && img.storageType != storage.pccSto).storageType; imgInfo.uncSize = imgFile.resize().Length; imgInfo.cprSize = imgFile.resize().Length; } switch (imgInfo.storageType) { case storage.arcCpr: case storage.arcUnc: string archivePath = FullArcPath; if (String.IsNullOrEmpty(archivePath)) archivePath = GetTexArchive(archiveDir); if (!File.Exists(archivePath)) throw new FileNotFoundException("Texture archive not found in " + archivePath); imgBuffer = imgFile.imgData; if (imgBuffer.Length != imgInfo.uncSize) throw new FormatException("image sizes do not match, original is " + imgInfo.uncSize + ", new is " + imgBuffer.Length); if (arcName.Length <= CustCache.Length || arcName.Substring(0, CustCache.Length) != CustCache) // Check whether existing texture is in a custom cache { ChooseNewCache(archiveDir, imgBuffer.Length); archivePath = FullArcPath; } else { FileInfo arc = new FileInfo(archivePath); if (arc.Length + imgBuffer.Length >= 0x80000000) { ChooseNewCache(archiveDir, imgBuffer.Length); archivePath = FullArcPath; } } using (FileStream archiveStream = new FileStream(archivePath, FileMode.Append, FileAccess.Write)) { int newOffset = (int)archiveStream.Position; if (imgInfo.storageType == storage.arcCpr) { byte[] tempBuff; SaltLZOHelper lzohelper = new SaltLZOHelper(); tempBuff = lzohelper.CompressTex(imgBuffer); imgBuffer = new byte[tempBuff.Length]; Buffer.BlockCopy(tempBuff, 0, imgBuffer, 0, tempBuff.Length); imgInfo.cprSize = imgBuffer.Length; } archiveStream.Write(imgBuffer, 0, imgBuffer.Length); imgInfo.offset = newOffset; } break; case storage.pccSto: imgBuffer = imgFile.resize(); using (MemoryStream dataStream = new MemoryStream()) { dataStream.WriteBytes(imageData); if (imgBuffer.Length <= imgInfo.uncSize && imgInfo.offset > 0) dataStream.Seek(imgInfo.offset, SeekOrigin.Begin); else imgInfo.offset = (int)dataStream.Position; dataStream.WriteBytes(imgBuffer); imgInfo.cprSize = imgBuffer.Length; imgInfo.uncSize = imgBuffer.Length; imageData = dataStream.ToArray(); } break; } imgList[imageIdx] = imgInfo; }
public void addBiggerImage(string imagePathToAdd, string archiveDir) { ImageSize biggerImageSizeOnList = imgList.Max(image => image.imgSize); // check if replacing image is supported ImageFile imgFile; string fileFormat = Path.GetExtension(imagePathToAdd); switch (fileFormat) { case ".dds": imgFile = new DDS(imagePathToAdd, null); break; case ".DDS": imgFile = new DDS(imagePathToAdd, null); break; default: throw new FormatException(fileFormat + " image extension not supported"); } if (texFormat == "PF_NormalMap_HQ") { if (imgFile.format != "ATI2") throw new FormatException("Different image format, original is " + texFormat + ", new is " + imgFile.subtype()); } else if (String.Compare(texFormat, "PF_" + imgFile.format, true) != 0 && String.Compare(texFormat, imgFile.format, true) != 0) { throw new FormatException("Different image format, original is " + texFormat + ", new is " + imgFile.subtype()); } // check if image to add is valid if (biggerImageSizeOnList.width * 2 != imgFile.imgSize.width || biggerImageSizeOnList.height * 2 != imgFile.imgSize.height) throw new FormatException("image size " + imgFile.imgSize + " isn't valid, must be " + new ImageSize(biggerImageSizeOnList.width * 2, biggerImageSizeOnList.height * 2)); if (imgList.Count <= 1) throw new Exception("Unable to add image, texture must have more than one image present"); // !!! warning, this method breaks consistency between imgList and imageData[] !!! ImageInfo newImgInfo = new ImageInfo(); newImgInfo.storageType = imgList.Find(img => img.storageType != storage.empty && img.storageType != storage.pccSto).storageType; // for additional mipmaps keep them in external archive but only when // texture allready have such property if (properties.ContainsKey("TextureFileCacheName")) newImgInfo.storageType = storage.arcCpr; newImgInfo.imgSize = imgFile.imgSize; newImgInfo.uncSize = imgFile.resize().Length; newImgInfo.cprSize = 0x00; // not yet filled newImgInfo.offset = 0x00; // not yet filled imgList.Insert(0, newImgInfo); // insert new image on top of the list //now I let believe the program that I'm doing an image replace, saving lot of code ;) replaceImage(newImgInfo.imgSize.ToString(), imagePathToAdd, archiveDir); //updating num of images numMipMaps++; // update MipTailBaseIdx int propVal = properties["MipTailBaseIdx"].Value.IntValue; propVal++; properties["MipTailBaseIdx"].Value.IntValue = propVal; // update Sizes properties["SizeX"].Value.IntValue = (int)newImgInfo.imgSize.width; properties["SizeY"].Value.IntValue = (int)newImgInfo.imgSize.height; }