public void SetupSettings() { if (SelectedTexSettings.Format == SurfaceFormat.Invalid || SelectedIndex == -1) { return; } WidthLabel.Text = $"Width {SelectedTexSettings.TexWidth}"; HeightLabel.Text = $"Height {SelectedTexSettings.TexHeight}"; if (Thread != null && Thread.IsAlive) { Thread.Abort(); } if (formatComboBox.SelectedItem is SurfaceFormat) { SelectedTexSettings.Format = (SurfaceFormat)formatComboBox.SelectedItem; listViewCustom1.Items[SelectedIndex].SubItems[1].Text = SelectedTexSettings.Format.ToString(); } if (SelectedTexSettings.Format == SurfaceFormat.BC7_UNORM || SelectedTexSettings.Format == SurfaceFormat.BC7_SRGB) { compressionModeCB.Visible = true; } else { compressionModeCB.Visible = false; } Bitmap bitmap = Switch_Toolbox.Library.Imaging.GetLoadingImage(); if (compressionModeCB.SelectedIndex == 0) { CompressionMode = STCompressionMode.Fast; } else { CompressionMode = STCompressionMode.Normal; } Thread = new Thread((ThreadStart)(() => { SelectedTexSettings.IsFinishedCompressing = false; ToggleOkButton(false); pictureBox1.Image = bitmap; var mips = SelectedTexSettings.GenerateMipList(CompressionMode); SelectedTexSettings.DataBlockOutput.Clear(); SelectedTexSettings.DataBlockOutput.Add(Utils.CombineByteArray(mips.ToArray())); ToggleOkButton(true); SelectedTexSettings.IsFinishedCompressing = true; if (SelectedTexSettings.DataBlockOutput.Count > 0) { if (SelectedTexSettings.Format == SurfaceFormat.BC5_SNORM) { bitmap = DDSCompressor.DecompressBC5(mips[0], (int)SelectedTexSettings.TexWidth, (int)SelectedTexSettings.TexHeight, true); } else { bitmap = STGenericTexture.DecodeBlockGetBitmap(mips[0], SelectedTexSettings.TexWidth, SelectedTexSettings.TexHeight, TextureData.ConvertFormat(SelectedTexSettings.Format)); } } mips.Clear(); if (pictureBox1.InvokeRequired) { pictureBox1.Invoke((MethodInvoker) delegate { pictureBox1.Image = bitmap; pictureBox1.Refresh(); }); } })); Thread.Start(); }
public Texture FromBitMap(byte[] data, TextureImporterSettings settings) { Texture tex = new Texture(); tex.Height = (uint)settings.TexHeight; tex.Width = (uint)settings.TexWidth; var formats = TextureData.GetSurfaceFormat(settings.Format, settings.FormatType); tex.Format = formats.Item1; tex.FormatType = formats.Item2; tex.Name = settings.TexName; tex.Path = ""; tex.TextureData = new List <List <byte[]> >(); if (settings.MipCount == 0) { settings.MipCount = 1; } STChannelType[] channels = STGenericTexture.SetChannelsByFormat(settings.Format); tex.ChannelRed = (ChannelType)channels[0]; tex.ChannelGreen = (ChannelType)channels[1]; tex.ChannelBlue = (ChannelType)channels[2]; tex.ChannelAlpha = (ChannelType)channels[3]; tex.sparseBinding = settings.sparseBinding; tex.sparseResidency = settings.sparseResidency; tex.AccessFlags = settings.AccessFlags; tex.ArrayLength = settings.arrayLength; tex.MipCount = settings.MipCount; tex.Depth = settings.Depth; tex.Dim = settings.Dim; tex.Flags = settings.Flags; tex.TileMode = settings.TileMode; tex.textureLayout = settings.TextureLayout; tex.textureLayout2 = settings.TextureLayout2; tex.Swizzle = settings.Swizzle; tex.SurfaceDim = settings.SurfaceDim; tex.SampleCount = settings.SampleCount; tex.Regs = settings.Regs; tex.Pitch = settings.Pitch; tex.MipOffsets = new long[tex.MipCount]; List <byte[]> arrayFaces = new List <byte[]>(); if (tex.ArrayLength > 1) { arrayFaces = DDS.GetArrayFaces(data, tex.ArrayLength); } else { arrayFaces.Add(data); } for (int i = 0; i < tex.ArrayLength; i++) { List <byte[]> mipmaps = SwizzleSurfaceMipMaps(tex, arrayFaces[i], tex.TileMode); tex.TextureData.Add(mipmaps); byte[] test = Combine(mipmaps); tex.TextureData[i][0] = test; } return(tex); }
public void LoadDDS(string FileName, BntxFile bntxFile, byte[] FileData = null, TextureData tree = null) { TexName = Path.GetFileNameWithoutExtension(FileName); DDS dds = new DDS(); if (FileData != null) { dds.Load(new FileReader(new MemoryStream(FileData))); } else { dds.Load(new FileReader(FileName)); } MipCount = dds.header.mipmapCount; TexWidth = dds.header.width; TexHeight = dds.header.height; arrayLength = 1; if (dds.header.caps2 == (uint)DDS.DDSCAPS2.CUBEMAP_ALLFACES) { arrayLength = 6; } DataBlockOutput.Add(dds.bdata); var formats = dds.GetFormat(); Format = formats.Item1; FormatType = formats.Item2; Texture tex = FromBitMap(DataBlockOutput[0], this); if (tree != null) { tree.LoadTexture(tex, 1); } else { textureData = new TextureData(tex, bntxFile); } }
private void ReadGx2(FileReader reader) { reader.ByteOrder = Syroot.BinaryData.ByteOrder.BigEndian; header = new GTXHeader(); header.Read(reader); Console.WriteLine("header size " + header.HeaderSize); uint surfBlockType; uint dataBlockType; uint mipBlockType; if (header.MajorVersion == 6) { surfBlockType = 0x0A; dataBlockType = 0x0B; mipBlockType = 0x0C; } else if (header.MajorVersion == 7) { surfBlockType = 0x0B; dataBlockType = 0x0C; mipBlockType = 0x0D; } else { throw new Exception($"Unsupported GTX version {header.MajorVersion}"); } if (header.GpuVersion != 2) { throw new Exception($"Unsupported GPU version {header.GpuVersion}"); } reader.Position = header.HeaderSize; bool blockB = false; bool blockC = false; uint ImageInfo = 0; uint images = 0; while (reader.Position < reader.BaseStream.Length) { GTXDataBlock block = new GTXDataBlock(); block.Read(reader); blocks.Add(block); //Here we use "if" instead of "case" statements as types vary between versions if ((uint)block.BlockType == surfBlockType) { ImageInfo += 1; blockB = true; var surface = new SurfaceInfoParse(); surface.Read(new FileReader(block.data)); if (surface.numMips > 14) { throw new Exception($"Invalid number of mip maps {surface.numMips}!"); } TextureData textureData = new TextureData(); textureData.surface = surface; textureData.Text = "Texture" + ImageInfo; Nodes.Add(textureData); textures.Add(textureData); } else if ((uint)block.BlockType == dataBlockType) { images += 1; blockC = true; data.Add(block.data); } else if ((uint)block.BlockType == mipBlockType) { mipMaps.Add(block.data); } } if (textures.Count != data.Count) { throw new Exception($"Bad size! {textures.Count} {data.Count}"); } int curTex = 0; int curMip = 0; foreach (var node in Nodes) { TextureData tex = (TextureData)node; tex.surface.data = data[curTex]; tex.surface.bpp = GTX.surfaceGetBitsPerPixel(tex.surface.format) >> 3; Console.WriteLine(); if (tex.surface.numMips > 1) { tex.surface.mipData = mipMaps[curMip++]; } else { tex.surface.mipData = new byte[0]; } Console.WriteLine(""); Console.WriteLine("// ----- GX2Surface Info ----- "); Console.WriteLine(" dim = " + tex.surface.dim); Console.WriteLine(" width = " + tex.surface.width); Console.WriteLine(" height = " + tex.surface.height); Console.WriteLine(" depth = " + tex.surface.depth); Console.WriteLine(" numMips = " + tex.surface.numMips); Console.WriteLine(" format = " + tex.surface.format); Console.WriteLine(" aa = " + tex.surface.aa); Console.WriteLine(" use = " + tex.surface.use); Console.WriteLine(" imageSize = " + tex.surface.imageSize); Console.WriteLine(" mipSize = " + tex.surface.mipSize); Console.WriteLine(" tileMode = " + tex.surface.tileMode); Console.WriteLine(" swizzle = " + tex.surface.swizzle); Console.WriteLine(" alignment = " + tex.surface.alignment); Console.WriteLine(" pitch = " + tex.surface.pitch); Console.WriteLine(" bits per pixel = " + (tex.surface.bpp << 3)); Console.WriteLine(" bytes per pixel = " + tex.surface.bpp); Console.WriteLine(" data size = " + tex.surface.data.Length); Console.WriteLine(" mip size = " + tex.surface.mipData.Length); Console.WriteLine(" realSize = " + tex.surface.imageSize); List <byte[]> mips = GTX.Decode(tex.surface); tex.Surfaces.Add(new STGenericTexture.Surface() { mipmaps = mips }); tex.RenderableTex.LoadOpenGLTexture(tex); curTex++; } }
public List <byte[]> GenerateMipList(STCompressionMode CompressionMode, int SurfaceLevel = 0) { Bitmap Image = BitmapExtension.GetBitmap(DecompressedData[SurfaceLevel], (int)TexWidth, (int)TexHeight); List <byte[]> mipmaps = new List <byte[]>(); for (int mipLevel = 0; mipLevel < MipCount; mipLevel++) { int MipWidth = Math.Max(1, (int)TexWidth >> mipLevel); int MipHeight = Math.Max(1, (int)TexHeight >> mipLevel); if (mipLevel != 0) { Image = BitmapExtension.Resize(Image, MipWidth, MipHeight); } mipmaps.Add(STGenericTexture.CompressBlock(BitmapExtension.ImageToByte(Image), Image.Width, Image.Height, TextureData.ConvertFormat(Format), alphaRef, CompressionMode)); } Image.Dispose(); return(mipmaps); }
public static List <byte[]> SwizzleSurfaceMipMaps(Texture tex, byte[] data, uint MipCount) { var TexFormat = TextureData.ConvertFormat(tex.Format); int blockHeightShift = 0; int target = 1; uint Pitch = 0; uint SurfaceSize = 0; uint blockHeight = 0; uint blkWidth = STGenericTexture.GetBlockWidth(TexFormat); uint blkHeight = STGenericTexture.GetBlockHeight(TexFormat); uint blkDepth = STGenericTexture.GetBlockDepth(TexFormat); uint bpp = STGenericTexture.GetBytesPerPixel(TexFormat); uint linesPerBlockHeight = 0; if (tex.TileMode == TileMode.LinearAligned) { blockHeight = 1; tex.BlockHeightLog2 = 0; tex.Alignment = 1; linesPerBlockHeight = 1; tex.ReadTextureLayout = 0; } else { blockHeight = TegraX1Swizzle.GetBlockHeight(DIV_ROUND_UP(tex.Height, blkHeight)); tex.BlockHeightLog2 = (uint)Convert.ToString(blockHeight, 2).Length - 1; tex.Alignment = 512; tex.ReadTextureLayout = 1; linesPerBlockHeight = blockHeight * 8; } List <byte[]> mipmaps = new List <byte[]>(); for (int mipLevel = 0; mipLevel < MipCount; mipLevel++) { var result = TextureHelper.GetCurrentMipSize(tex.Width, tex.Height, blkWidth, blkHeight, bpp, mipLevel); uint offset = result.Item1; uint size = result.Item2; byte[] data_ = Utils.SubArray(data, offset, size); uint width_ = Math.Max(1, tex.Width >> mipLevel); uint height_ = Math.Max(1, tex.Height >> mipLevel); uint depth_ = Math.Max(1, tex.Depth >> mipLevel); uint width__ = DIV_ROUND_UP(width_, blkWidth); uint height__ = DIV_ROUND_UP(height_, blkHeight); uint depth__ = DIV_ROUND_UP(depth_, blkDepth); byte[] AlignedData = new byte[(TegraX1Swizzle.round_up(SurfaceSize, (uint)tex.Alignment) - SurfaceSize)]; SurfaceSize += (uint)AlignedData.Length; // Console.WriteLine("SurfaceSize Aligned " + AlignedData); Console.WriteLine("MipOffsets " + SurfaceSize); Console.WriteLine("size " + size); tex.MipOffsets[mipLevel] = SurfaceSize; if (tex.TileMode == TileMode.LinearAligned) { Pitch = width__ * bpp; if (target == 1) { Pitch = TegraX1Swizzle.round_up(width__ * bpp, 32); } SurfaceSize += Pitch * height__; } else { if (TegraX1Swizzle.pow2_round_up(height__) < linesPerBlockHeight) { blockHeightShift += 1; } Pitch = TegraX1Swizzle.round_up(width__ * bpp, 64); SurfaceSize += Pitch * TegraX1Swizzle.round_up(height__, Math.Max(1, blockHeight >> blockHeightShift) * 8); } byte[] SwizzledData = TegraX1Swizzle.swizzle(width_, height_, depth_, blkWidth, blkHeight, blkDepth, target, bpp, (uint)tex.TileMode, (int)Math.Max(0, tex.BlockHeightLog2 - blockHeightShift), data_); mipmaps.Add(AlignedData.Concat(SwizzledData).ToArray()); } tex.ImageSize = SurfaceSize; return(mipmaps); }
private void ReadGx2(FileReader reader) { reader.ByteOrder = Syroot.BinaryData.ByteOrder.BigEndian; header = new GTXHeader(); header.Read(reader); Console.WriteLine("header size " + header.HeaderSize); uint surfBlockType; uint dataBlockType; uint mipBlockType; uint vertexShaderHeader = 0x03; uint vertexShaderProgram = 0x05; uint pixelShaderHeader = 0x06; uint pixelShaderProgram = 0x07; uint geometryShaderHeader = 0x08; uint geometryShaderProgram = 0x09; uint userDataBlock = 0x10; if (header.MajorVersion == 6 && header.MinorVersion == 0) { surfBlockType = 0x0A; dataBlockType = 0x0B; mipBlockType = 0x0C; } else if (header.MajorVersion == 6 || header.MajorVersion == 7) { surfBlockType = 0x0B; dataBlockType = 0x0C; mipBlockType = 0x0D; } else { throw new Exception($"Unsupported GTX version {header.MajorVersion}"); } if (header.GpuVersion != 2) { throw new Exception($"Unsupported GPU version {header.GpuVersion}"); } reader.Position = header.HeaderSize; bool blockB = false; bool blockC = false; uint ImageInfo = 0; uint images = 0; while (reader.Position < reader.BaseStream.Length) { Console.WriteLine("BLOCK POS " + reader.Position + " " + reader.BaseStream.Length); GTXDataBlock block = new GTXDataBlock(); block.Read(reader); blocks.Add(block); bool BlockIsEmpty = block.BlockType == BlockType.AlignData || block.BlockType == BlockType.EndOfFile; //Here we use "if" instead of "case" statements as types vary between versions if ((uint)block.BlockType == surfBlockType) { ImageInfo += 1; blockB = true; var surface = new SurfaceInfoParse(); surface.Read(new FileReader(block.data)); if (surface.tileMode == 0 || surface.tileMode > 16) { throw new Exception($"Invalid tileMode {surface.tileMode}!"); } if (surface.numMips > 14) { throw new Exception($"Invalid number of mip maps {surface.numMips}!"); } TextureData textureData = new TextureData(); textureData.surface = surface; textureData.MipCount = surface.numMips; textureData.ArrayCount = surface.depth; textureData.Text = "Texture" + ImageInfo; Nodes.Add(textureData); textures.Add(textureData); } else if ((uint)block.BlockType == dataBlockType) { images += 1; blockC = true; data.Add(block.data); } else if ((uint)block.BlockType == mipBlockType) { mipMaps.Add(block.data); } else if ((uint)block.BlockType == vertexShaderHeader) { Nodes.Add(new BlockDisplay(block.data) { Text = "Vertex Shader Header" }); } else if ((uint)block.BlockType == vertexShaderProgram) { Nodes.Add(new BlockDisplay(block.data) { Text = "Vertex Shader Program" }); } else if ((uint)block.BlockType == pixelShaderHeader) { Nodes.Add(new BlockDisplay(block.data) { Text = "Pixel Shader Header" }); } else if ((uint)block.BlockType == pixelShaderProgram) { Nodes.Add(new BlockDisplay(block.data) { Text = "Pixel Shader Program" }); } else if ((uint)block.BlockType == geometryShaderHeader) { Nodes.Add(new BlockDisplay(block.data) { Text = "Geometry Shader Header" }); } else if ((uint)block.BlockType == geometryShaderProgram) { Nodes.Add(new BlockDisplay(block.data) { Text = "Geometry Shader Program" }); } else if (!BlockIsEmpty) { Nodes.Add(new BlockDisplay(block.data) { Text = $"Block Type {block.BlockType.ToString("X")}" }); } } if (textures.Count != data.Count) { throw new Exception($"Bad size! {textures.Count} {data.Count}"); } int curTex = 0; int curMip = 0; foreach (var node in Nodes) { if (node is TextureData) { TextureData tex = (TextureData)node; tex.surface.data = data[curTex]; tex.surface.bpp = GX2.surfaceGetBitsPerPixel(tex.surface.format) >> 3; tex.Format = FTEX.ConvertFromGx2Format((Syroot.NintenTools.Bfres.GX2.GX2SurfaceFormat)tex.surface.format); tex.Width = tex.surface.width; tex.Height = tex.surface.height; if (tex.surface.numMips > 1) { tex.surface.mipData = mipMaps[curMip++]; } else { tex.surface.mipData = new byte[0]; } if (tex.surface.mipData == null) { tex.surface.numMips = 1; } curTex++; } } }
public void LoadTexture(TextureData tex) { TextureData.BRTI_Texture renderedTex = tex.renderedGLTex; bntxEditor1.LoadProperty(tex); }
public void RemoveTexture(TextureData textureData) { Nodes.Remove(textureData); Textures.Remove(textureData.Text); Viewport.Instance.UpdateViewport(); }
public void Compress() { DataBlockOutput.Clear(); foreach (var surface in DecompressedData) { DataBlockOutput.Add(STGenericTexture.CompressBlock(surface, (int)TexWidth, (int)TexHeight, TextureData.ConvertFormat(Format), alphaRef)); } }
public void InitializeTextureListView(FMAT material) { textureRefListView.Items.Clear(); textureRefListView.SmallImageList = textureImageList; textureRefListView.FullRowSelect = true; foreach (MatTexture tex in material.textures) { ListViewItem item = new ListViewItem(); item.Text = tex.Name; item.SubItems.Add(tex.SamplerName); if (material.shaderassign.samplers.ContainsValue(tex.SamplerName)) { var FragSampler = material.shaderassign.samplers.FirstOrDefault(x => x.Value == tex.SamplerName).Key; item.SubItems.Add(FragSampler.ToString()); } textureRefListView.Items.Add(item); } textureImageList.Images.Clear(); int CurTex = 0; if (PluginRuntime.bntxContainers.Count == 0 && PluginRuntime.ftexContainers.Count == 0) { foreach (ListViewItem item in textureRefListView.Items) { AddBlankTexture(item, item.Text, CurTex++); } } bool FoundTexture = false; foreach (ListViewItem item in textureRefListView.Items) { foreach (BinaryTextureContainer bntx in PluginRuntime.bntxContainers) { if (bntx.Textures.ContainsKey(item.Text)) { FoundTexture = true; TextureData tex = bntx.Textures[item.Text]; TextureData.BRTI_Texture renderedTex = tex.renderedGLTex; Bitmap temp = tex.GLTextureToBitmap(renderedTex, renderedTex.display); textureImageList.Images.Add(tex.Text, temp); item.ImageIndex = CurTex++; var dummy = textureImageList.Handle; temp.Dispose(); } } foreach (FTEXContainer ftexCont in PluginRuntime.ftexContainers) { if (ftexCont.Textures.ContainsKey(item.Text)) { FoundTexture = true; FTEX tex = ftexCont.Textures[item.Text]; FTEX.RenderableTex renderedTex = tex.renderedTex; Bitmap temp = tex.GLTextureToBitmap(renderedTex, renderedTex.display); textureImageList.Images.Add(tex.Text, temp); item.ImageIndex = CurTex++; var dummy = textureImageList.Handle; temp.Dispose(); } } if (FoundTexture == false) { AddBlankTexture(item, item.Text, CurTex++); } } }
public byte[] GenerateMips(int SurfaceLevel = 0) { Bitmap Image = BitmapExtension.GetBitmap(DecompressedData[SurfaceLevel], (int)TexWidth, (int)TexHeight); List <byte[]> mipmaps = new List <byte[]>(); mipmaps.Add(STGenericTexture.CompressBlock(DecompressedData[SurfaceLevel], (int)TexWidth, (int)TexHeight, TextureData.ConvertFormat(Format), alphaRef)); //while (Image.Width / 2 > 0 && Image.Height / 2 > 0) // for (int mipLevel = 0; mipLevel < MipCount; mipLevel++) for (int mipLevel = 0; mipLevel < MipCount; mipLevel++) { int width = Image.Width / 2; int height = Image.Height / 2; if (width <= 0) { width = 1; } if (height <= 0) { height = 1; } Image = BitmapExtension.Resize(Image, width, height); mipmaps.Add(STGenericTexture.CompressBlock(BitmapExtension.ImageToByte(Image), Image.Width, Image.Height, TextureData.ConvertFormat(Format), alphaRef)); } Image.Dispose(); return(Utils.CombineByteArray(mipmaps.ToArray())); }
public void SetupSettings() { if (SelectedTexSettings.Format == SurfaceFormat.Invalid) { return; } WidthLabel.Text = $"Width {SelectedTexSettings.TexWidth}"; HeightLabel.Text = $"Height {SelectedTexSettings.TexHeight}"; if (formatComboBox.SelectedItem is SurfaceFormat) { SelectedTexSettings.Format = (SurfaceFormat)formatComboBox.SelectedItem; listViewCustom1.SelectedItems[0].SubItems[1].Text = SelectedTexSettings.Format.ToString(); } Bitmap bitmap = Switch_Toolbox.Library.Imaging.GetLoadingImage(); Thread = new Thread((ThreadStart)(() => { ToggleOkButton(false); pictureBox1.Image = bitmap; SelectedTexSettings.Compress(); ToggleOkButton(true); if (SelectedTexSettings.Format == SurfaceFormat.BC5_SNORM) { bitmap = DDSCompressor.DecompressBC5(SelectedTexSettings.DataBlockOutput[0], (int)SelectedTexSettings.TexWidth, (int)SelectedTexSettings.TexHeight, true); } else { bitmap = TextureData.DecodeBlockGetBitmap(SelectedTexSettings.DataBlockOutput[0], SelectedTexSettings.TexWidth, SelectedTexSettings.TexHeight, TextureData.ConvertFormat(SelectedTexSettings.Format)); } if (pictureBox1.InvokeRequired) { pictureBox1.Invoke((MethodInvoker) delegate { pictureBox1.Image = bitmap; pictureBox1.Refresh(); }); } })); Thread.Start(); }
public override void Replace(string FileName) { var bntxFile = new BNTX(); var tex = new TextureData(); tex.Replace(FileName, MipCount, 0, Format); //If it's null, the operation is cancelled if (tex.Texture == null) { return; } var surfacesNew = tex.GetSurfaces(); var surfaces = GetSurfaces(); if (LimitFileSize) { if (surfaces[0].mipmaps[0].Length < surfacesNew[0].mipmaps[0].Length) { if (surfaces[0].mipmaps[0].Length != surfacesNew[0].mipmaps[0].Length) { throw new Exception($"Image must be the same size! {surfaces[0].mipmaps[0].Length}"); } if (mipSizes[0].Length != surfacesNew[0].mipmaps.Count) { throw new Exception($"Mip map count must be the same! {mipSizes[0].Length}"); } if (Width != tex.Texture.Width || Height != tex.Texture.Height) { throw new Exception("Image size must be the same!"); } } Width = tex.Texture.Width; Height = tex.Texture.Height; MipCount = tex.Texture.MipCount; } else { Width = tex.Texture.Width; Height = tex.Texture.Height; MipCount = tex.Texture.MipCount; ArrayCount = tex.Texture.ArrayLength; Depth = tex.Texture.Depth; Format = tex.Format; NutFormat = ConvertGenericToNutFormat(tex.Format); mipSizes = TegraX1Swizzle.GenerateMipSizes(tex.Format, tex.Width, tex.Height, tex.Depth, tex.ArrayCount, tex.MipCount, (uint)ImageData.Length); } List <byte[]> data = new List <byte[]>(); foreach (var array in tex.Texture.TextureData) { data.Add(Utils.CombineByteArray(array.ToArray())); } var output = Utils.CombineByteArray(data.ToArray()); ImageData = SetImageData(output); data.Clear(); surfacesNew.Clear(); surfaces.Clear(); UpdateEditor(); }
public byte[] GenerateMips(STCompressionMode CompressionMode, bool multiThread, int SurfaceLevel = 0) { Bitmap Image = BitmapExtension.GetBitmap(DecompressedData[SurfaceLevel], (int)TexWidth, (int)TexHeight); if (GammaFix) { Image = BitmapExtension.AdjustGamma(Image, 2.2f); } List <byte[]> mipmaps = new List <byte[]>(); for (int mipLevel = 0; mipLevel < MipCount; mipLevel++) { int MipWidth = Math.Max(1, (int)TexWidth >> mipLevel); int MipHeight = Math.Max(1, (int)TexHeight >> mipLevel); if (mipLevel != 0) { Image = BitmapExtension.Resize(Image, MipWidth, MipHeight); } mipmaps.Add(STGenericTexture.CompressBlock(BitmapExtension.ImageToByte(Image), Image.Width, Image.Height, TextureData.ConvertFormat(Format), alphaRef, multiThread, CompressionMode)); } Image.Dispose(); return(Utils.CombineByteArray(mipmaps.ToArray())); }
public void SetupSettings(TextureImporterSettings setting, bool setFormat = true) { if (setting.Format == SurfaceFormat.Invalid || SelectedIndex == -1) { return; } WidthLabel.Text = $"Width: {setting.TexWidth}"; HeightLabel.Text = $"Height: {setting.TexHeight}"; if (Thread != null && Thread.IsAlive) { Thread.Abort(); } if (formatComboBox.SelectedItem is SurfaceDim && setFormat) { setting.SurfaceDim = (SurfaceDim)formatComboBox.SelectedItem; } if (formatComboBox.SelectedItem is SurfaceFormat && setFormat) { setting.Format = (SurfaceFormat)formatComboBox.SelectedItem; listViewCustom1.Items[SelectedIndex].SubItems[1].Text = setting.Format.ToString(); } if (setting.Format == SurfaceFormat.BC7_UNORM || setting.Format == SurfaceFormat.BC7_SRGB) { compressionModeCB.Visible = true; compModeLbl.Visible = true; } else { compressionModeCB.Visible = false; compModeLbl.Visible = false; } if (setting.Format == SurfaceFormat.BC4_UNORM || setting.Format == SurfaceFormat.BC4_SNORM) { chkBC4Alpha.Enabled = true; } else { chkBC4Alpha.Enabled = false; } Bitmap bitmap = Toolbox.Library.Imaging.GetLoadingImage(); if (compressionModeCB.SelectedIndex == 0) { CompressionMode = STCompressionMode.Fast; } else { CompressionMode = STCompressionMode.Normal; } Thread = new Thread((ThreadStart)(() => { setting.IsFinishedCompressing = false; ToggleOkButton(false); pictureBox1.Image = bitmap; var mips = setting.GenerateMipList(CompressionMode, MultiThreading, chkBC4Alpha.Checked); setting.DataBlockOutput.Clear(); setting.DataBlockOutput.Add(Utils.CombineByteArray(mips.ToArray())); ToggleOkButton(true); setting.IsFinishedCompressing = true; if (setting.DataBlockOutput.Count > 0) { if (setting.Format == SurfaceFormat.BC5_SNORM) { bitmap = DDSCompressor.DecompressBC5(mips[0], (int)setting.TexWidth, (int)setting.TexHeight, true); } else { bitmap = STGenericTexture.DecodeBlockGetBitmap(mips[0], setting.TexWidth, setting.TexHeight, TextureData.ConvertFormat(setting.Format), new byte[0]); } if (chkBC4Alpha.Checked) { bitmap = BitmapExtension.SetChannel(bitmap, STChannelType.Red, STChannelType.Red, STChannelType.Red, STChannelType.Red); } } if (pictureBox1.InvokeRequired) { pictureBox1.Invoke((MethodInvoker) delegate { pictureBox1.Image = bitmap; pictureBox1.Refresh(); int size = Utils.GetSizeInBytes(mips); dataSizeLbl.Text = $"Data Size: {STMath.GetFileSize(size, 5)}"; }); } mips.Clear(); })); Thread.Start(); }
public void Compress(STCompressionMode CompressionMode, bool multiThread) { DataBlockOutput.Clear(); foreach (var surface in DecompressedData) { DataBlockOutput.Add(STGenericTexture.CompressBlock(surface, (int)TexWidth, (int)TexHeight, TextureData.ConvertFormat(Format), alphaRef, multiThread, CompressionMode)); } }
public void LoadTexture(TextureData tex) { TextureData.BRTI_Texture renderedTex = tex.renderedGLTex; bntxEditor1.LoadPicture(tex.GLTextureToBitmap(renderedTex, renderedTex.display)); bntxEditor1.LoadProperty(tex); }
public override void Replace(string FileName) { if (IsSwizzled) { var tex = new TextureData(); tex.Replace(FileName, MipCount, 0, Format); //If it's null, the operation is cancelled if (tex.Texture == null) { return; } List <byte[]> data = new List <byte[]>(); foreach (var array in tex.Texture.TextureData) { data.Add(array[0]); } var output = CreateBuffer(data); Width = tex.Texture.Width; Height = tex.Texture.Height; MipCount = tex.Texture.MipCount; // ArrayCount = tex.Texture.ArrayLength; // Depth = tex.Texture.Depth; Format = tex.Format; NutFormat = ConvertGenericToNutFormat(tex.Format); mipSizes = TegraX1Swizzle.GenerateMipSizes(tex.Format, tex.Width, tex.Height, tex.Depth, tex.ArrayCount, tex.MipCount, (uint)ImageData.Length); ImageData = SetImageData(output); data.Clear(); } else { GenericTextureImporterList importer = new GenericTextureImporterList(SupportedFormats); GenericTextureImporterSettings settings = new GenericTextureImporterSettings(); if (Utils.GetExtension(FileName) == ".dds" || Utils.GetExtension(FileName) == ".dds2") { settings.LoadDDS(FileName); importer.LoadSettings(new List <GenericTextureImporterSettings>() { settings, }); ApplySettings(settings); UpdateEditor(); } else { settings.LoadBitMap(FileName); importer.LoadSettings(new List <GenericTextureImporterSettings>() { settings, }); if (importer.ShowDialog() == DialogResult.OK) { if (settings.GenerateMipmaps && !settings.IsFinishedCompressing) { settings.DataBlockOutput.Clear(); settings.DataBlockOutput.Add(settings.GenerateMips(importer.CompressionMode, importer.MultiThreading)); } ApplySettings(settings); UpdateEditor(); } } } UpdateEditor(); }
private void ReadGx2(FileReader reader) { reader.ByteOrder = Syroot.BinaryData.ByteOrder.BigEndian; header = new GTXHeader(); header.Read(reader); Console.WriteLine("header size " + header.HeaderSize); uint surfBlockType; uint dataBlockType; uint mipBlockType; if (header.MajorVersion == 6) { surfBlockType = 0x0A; dataBlockType = 0x0B; mipBlockType = 0x0C; } else if (header.MajorVersion == 7) { surfBlockType = 0x0B; dataBlockType = 0x0C; mipBlockType = 0x0D; } else { throw new Exception($"Unsupported GTX version {header.MajorVersion}"); } if (header.GpuVersion != 2) { throw new Exception($"Unsupported GPU version {header.GpuVersion}"); } reader.Position = header.HeaderSize; bool blockB = false; bool blockC = false; uint ImageInfo = 0; uint images = 0; while (reader.Position < reader.BaseStream.Length) { GTXDataBlock block = new GTXDataBlock(); block.Read(reader); blocks.Add(block); //Here we use "if" instead of "case" statements as types vary between versions if ((uint)block.BlockType == surfBlockType) { ImageInfo += 1; blockB = true; var surface = new SurfaceInfoParse(); surface.Read(new FileReader(block.data)); if (surface.numMips > 14) { throw new Exception($"Invalid number of mip maps {surface.numMips}!"); } TextureData textureData = new TextureData(); textureData.surface = surface; textureData.MipCount = surface.numMips; textureData.ArrayCount = surface.numArray; textureData.Text = "Texture" + ImageInfo; Nodes.Add(textureData); textures.Add(textureData); } else if ((uint)block.BlockType == dataBlockType) { images += 1; blockC = true; data.Add(block.data); } else if ((uint)block.BlockType == mipBlockType) { mipMaps.Add(block.data); } } if (textures.Count != data.Count) { throw new Exception($"Bad size! {textures.Count} {data.Count}"); } int curTex = 0; int curMip = 0; foreach (var node in Nodes) { TextureData tex = (TextureData)node; tex.surface.data = data[curTex]; tex.surface.bpp = GTX.surfaceGetBitsPerPixel(tex.surface.format) >> 3; tex.Format = FTEX.ConvertFromGx2Format((Syroot.NintenTools.Bfres.GX2.GX2SurfaceFormat)tex.surface.format); tex.Width = tex.surface.width; tex.Height = tex.surface.height; if (tex.surface.numMips > 1) { tex.surface.mipData = mipMaps[curMip++]; } else { tex.surface.mipData = new byte[0]; } if (tex.surface.mipData == null) { tex.surface.numMips = 1; } curTex++; } reader.Close(); reader.Dispose(); }