public void SetupSettings(GTXImporterSettings setting) { if (setting.Format == GX2.GX2SurfaceFormat.INVALID || SelectedIndex == -1) { return; } if (Thread != null && Thread.IsAlive) { Thread.Abort(); } if (formatComboBox.SelectedItem is GX2.GX2SurfaceFormat) { setting.Format = (GX2.GX2SurfaceFormat)formatComboBox.SelectedItem; listViewCustom1.Items[SelectedIndex].SubItems[1].Text = setting.Format.ToString(); } HeightLabel.Text = $"Height: {setting.TexHeight}"; WidthLabel.Text = $"Width: {setting.TexWidth}"; Bitmap bitmap = Toolbox.Library.Imaging.GetLoadingImage(); pictureBox1.Image = bitmap; Thread = new Thread((ThreadStart)(() => { setting.IsFinishedCompressing = false; ToggleOkButton(false); var mips = setting.GenerateMipList(); setting.DataBlockOutput.Clear(); setting.DataBlockOutput.Add(Utils.CombineByteArray(mips.ToArray())); ToggleOkButton(true); setting.Compress(); bitmap = FTEX.DecodeBlockGetBitmap(mips[0], setting. TexWidth, setting.TexHeight, FTEX.ConvertFromGx2Format( (Syroot.NintenTools.Bfres.GX2.GX2SurfaceFormat)setting.Format), new byte[0]); 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() { DataBlockOutput.Clear(); foreach (var surface in DecompressedData) { DataBlockOutput.Add(FTEX.CompressBlock(surface, (int)TexWidth, (int)TexHeight, FTEX.ConvertFromGx2Format((GX2SurfaceFormat)Format), alphaRef)); } }
public override void Replace(string FileName) { FTEX ftex = new FTEX(); ftex.ReplaceTexture(FileName, Format); if (ftex.texture != null) { surface.swizzle = ftex.texture.Swizzle; surface.tileMode = (uint)ftex.texture.TileMode; surface.format = (uint)ftex.texture.Format; surface.aa = (uint)ftex.texture.AAMode; surface.use = (uint)ftex.texture.Use; surface.alignment = (uint)ftex.texture.Alignment; surface.dim = (uint)ftex.texture.Dim; surface.width = (uint)ftex.texture.Width; surface.height = (uint)ftex.texture.Height; surface.depth = (uint)ftex.texture.Depth; surface.numMips = (uint)ftex.texture.MipCount; surface.imageSize = (uint)ftex.texture.Data.Length; surface.mipSize = (uint)ftex.texture.MipData.Length; surface.data = ftex.texture.Data; surface.mipData = ftex.texture.MipData; surface.mipOffset = ftex.texture.MipOffsets; surface.firstMip = ftex.texture.ViewMipFirst; surface.firstSlice = 0; surface.numSlices = ftex.texture.ArrayLength; surface.imageCount = ftex.texture.MipCount; surface.pitch = ftex.texture.Pitch; surface.texRegs = GX2.CreateRegisters(surface); SetChannelComponents(); Format = FTEX.ConvertFromGx2Format((Syroot.NintenTools.Bfres.GX2.GX2SurfaceFormat)surface.format); Width = surface.width; Height = surface.height; MipCount = surface.numMips; ArrayCount = surface.depth; ImageEditorBase editor = (ImageEditorBase)LibraryGUI.GetActiveContent(typeof(ImageEditorBase)); if (editor != null) { 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; 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 byte[] GenerateMips(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, FTEX.ConvertFromGx2Format((GX2SurfaceFormat)Format), alphaRef)); } Image.Dispose(); return(Utils.CombineByteArray(mipmaps.ToArray())); }
public void SetupSettings() { if (SelectedTexSettings.Format == GTX.GX2SurfaceFormat.INVALID) { return; } if (Thread != null && Thread.IsAlive) { Thread.Abort(); } if (formatComboBox.SelectedItem is GTX.GX2SurfaceFormat) { SelectedTexSettings.Format = (GTX.GX2SurfaceFormat)formatComboBox.SelectedItem; listViewCustom1.SelectedItems[0].SubItems[1].Text = SelectedTexSettings.Format.ToString(); } HeightLabel.Text = $"Height: {SelectedTexSettings.TexHeight}"; WidthLabel.Text = $"Width: {SelectedTexSettings.TexWidth}"; Bitmap bitmap = Switch_Toolbox.Library.Imaging.GetLoadingImage(); Thread = new Thread((ThreadStart)(() => { pictureBox1.Image = bitmap; SelectedTexSettings.Compress(); bitmap = FTEX.DecodeBlockGetBitmap(SelectedTexSettings.DataBlockOutput[0], SelectedTexSettings. TexWidth, SelectedTexSettings.TexHeight, FTEX.ConvertFromGx2Format( (Syroot.NintenTools.Bfres.GX2.GX2SurfaceFormat)SelectedTexSettings.Format)); pictureBox1.Image = bitmap; })); Thread.Start(); }
public void SetupSettings(GTXImporterSettings setting, bool setFormat = true) { if (setting.Format == GX2.GX2SurfaceFormat.INVALID || SelectedIndex == -1) { return; } if (Thread != null && Thread.IsAlive) { Thread.Abort(); } if (formatComboBox.SelectedItem is GX2.GX2SurfaceFormat && setFormat) { setting.Format = (GX2.GX2SurfaceFormat)formatComboBox.SelectedItem; if (setting.Format == GX2.GX2SurfaceFormat.T_BC4_UNORM && DisplayBC4Alpha || setting.Format == GX2.GX2SurfaceFormat.T_BC4_SNORM && DisplayBC4Alpha) { chkBc4Alpha.Visible = true; } else { chkBc4Alpha.Visible = false; } listViewCustom1.Items[SelectedIndex].SubItems[1].Text = setting.Format.ToString(); } if (setting.MipCountOriginal >= 0) { chkOriginalMipCount.Enabled = true; } else { chkOriginalMipCount.Enabled = false; } HeightLabel.Text = $"Height: {setting.TexHeight}"; WidthLabel.Text = $"Width: {setting.TexWidth}"; Bitmap bitmap = Toolbox.Library.Imaging.GetLoadingImage(); pictureBox1.Image = bitmap; Thread = new Thread((ThreadStart)(() => { setting.IsFinishedCompressing = false; ToggleOkButton(false); var mips = setting.GenerateMipList(); setting.DataBlockOutput.Clear(); setting.DataBlockOutput.Add(Utils.CombineByteArray(mips.ToArray())); ToggleOkButton(true); setting.IsFinishedCompressing = true; bitmap = FTEX.DecodeBlockGetBitmap(mips[0], setting. TexWidth, setting.TexHeight, FTEX.ConvertFromGx2Format( (Syroot.NintenTools.Bfres.GX2.GX2SurfaceFormat)setting.Format), new byte[0]); if (setting.FlipY) { bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY); } if (setting.UseBc4Alpha) { 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 List <byte[]> GenerateMipList(int SurfaceLevel = 0) { Bitmap Image = BitmapExtension.GetBitmap(DecompressedData[SurfaceLevel], (int)TexWidth, (int)TexHeight); if (FlipY) { Image.RotateFlip(RotateFlipType.RotateNoneFlipY); } if (UseBc4Alpha && (Format == GX2.GX2SurfaceFormat.T_BC4_UNORM || Format == GX2.GX2SurfaceFormat.T_BC4_SNORM)) { Image = BitmapExtension.SetChannel(Image, STChannelType.Alpha, STChannelType.Alpha, STChannelType.Alpha, STChannelType.One); } Console.WriteLine($"FlipY {FlipY}"); 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, FTEX.ConvertFromGx2Format((GX2SurfaceFormat)Format), alphaRef)); } Image.Dispose(); return(mipmaps); }
public void SetupSettings() { if (SelectedTexSettings.Format == GX2.GX2SurfaceFormat.INVALID || SelectedIndex == -1) { return; } if (Thread != null && Thread.IsAlive) { Thread.Abort(); } if (formatComboBox.SelectedItem is GX2.GX2SurfaceFormat) { SelectedTexSettings.Format = (GX2.GX2SurfaceFormat)formatComboBox.SelectedItem; listViewCustom1.Items[SelectedIndex].SubItems[1].Text = SelectedTexSettings.Format.ToString(); } HeightLabel.Text = $"Height: {SelectedTexSettings.TexHeight}"; WidthLabel.Text = $"Width: {SelectedTexSettings.TexWidth}"; Bitmap bitmap = Switch_Toolbox.Library.Imaging.GetLoadingImage(); Thread = new Thread((ThreadStart)(() => { SelectedTexSettings.IsFinishedCompressing = false; ToggleOkButton(false); var mips = SelectedTexSettings.GenerateMipList(); SelectedTexSettings.DataBlockOutput.Clear(); SelectedTexSettings.DataBlockOutput.Add(Utils.CombineByteArray(mips.ToArray())); ToggleOkButton(true); pictureBox1.Image = bitmap; SelectedTexSettings.Compress(); bitmap = FTEX.DecodeBlockGetBitmap(mips[0], SelectedTexSettings. TexWidth, SelectedTexSettings.TexHeight, FTEX.ConvertFromGx2Format( (Syroot.NintenTools.Bfres.GX2.GX2SurfaceFormat)SelectedTexSettings.Format)); pictureBox1.Image = bitmap; })); Thread.Start(); }
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(); }