Merge pull request #103 from JohnFiddleystein/master

Reading BTI and TXE files successfully and fixing the (GC) enums for some more GC image formats
This commit is contained in:
KillzXGaming 2019-08-04 11:26:13 -04:00 committed by GitHub
commit de3aa521ed
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 414 additions and 50 deletions

BIN
.vs/Toolbox/v16/.suo Normal file

Binary file not shown.

View file

Binary file not shown.

View file

@ -385,27 +385,27 @@ namespace FirstPlugin
var data = GenerateMipsAndCompress(bitmap, MipCount, Format);
//Swizzle and create surface
/* var surface = GX2.CreateGx2Texture(data, Text,
(uint)image.TileMode,
(uint)0,
(uint)image.Width,
(uint)image.Height,
(uint)1,
(uint)Gx2Format,
(uint)0,
(uint)1,
(uint)MipCount
);
/* var surface = GX2.CreateGx2Texture(data, Text,
(uint)image.TileMode,
(uint)0,
(uint)image.Width,
(uint)image.Height,
(uint)1,
(uint)Gx2Format,
(uint)0,
(uint)1,
(uint)MipCount
);
image.Swizzle = (byte)surface.swizzle;
image.BCLIMFormat = ConvertFormatGenericToBflim(Format);
image.Height = (ushort)surface.height;
image.Width = (ushort)surface.width;*/
image.Swizzle = (byte)surface.swizzle;
image.BCLIMFormat = ConvertFormatGenericToBflim(Format);
image.Height = (ushort)surface.height;
image.Width = (ushort)surface.width;*/
Width = image.Width;
Height = image.Height;
// ImageData = surface.data;
// ImageData = surface.data;
IsEdited = true;
LoadOpenGLTexture();

View file

@ -0,0 +1,179 @@
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using Toolbox.Library;
using Toolbox.Library.Forms;
using Toolbox.Library.IO;
namespace FirstPlugin
{
class BTI : STGenericTexture, IFileFormat, ISingleTextureIconLoader
{
public STGenericTexture IconTexture { get { return this; } }
public FileType FileType { get; set; } = FileType.Image;
public bool CanSave { get; set; }
public string[] Description { get; set; } = new string[] { "Binary Texture Image" };
public string[] Extension { get; set; } = new string[] { "*.bti" };
public string FileName { get; set; }
public string FilePath { get; set; }
//Stores compression info from being opened (done automaitcally)
public IFileInfo IFileInfo { get; set; }
//Check how the file wil be opened
public bool Identify(System.IO.Stream stream)
{
return Utils.HasExtension(FileName, ".bti");
}
//A Type list for custom types
//With this you can add in classes with IFileMenuExtension to add menus for this format
public Type[] Types
{
get
{
List<Type> types = new List<Type>();
return types.ToArray();
}
}
private int RoundWidth(int width, int BlockWidth)
{
return width + ((BlockWidth - (width % BlockWidth)) % BlockWidth);
}
private int RoundHeight(int height, int BlockHeight)
{
return height + ((BlockHeight - (height % BlockHeight)) % BlockHeight);
}
private void Read(System.IO.Stream stream)
{
}
public void Load(System.IO.Stream stream)
{
//Set this if you want to save the file format
CanSave = true;
CanEdit = false;
ImageKey = "Texture";
SelectedImageKey = "Texture";
Text = FileName;
//You can add a FileReader with Toolbox.Library.IO namespace
using (var reader = new FileReader(stream))
{
CanEdit = false;
reader.SetByteOrder(true);
//Turn this format into a common format used by this tool
byte texFormat = reader.ReadByte();
Format = Decode_Gamecube.ToGenericFormat((Decode_Gamecube.TextureFormats)texFormat);
reader.ReadByte(); // enable alpha
Width = reader.ReadUInt16();
Height = reader.ReadUInt16();
reader.ReadByte(); // wrap s
reader.ReadByte(); // wrap t
PaletteFormat = (PALETTE_FORMAT)reader.ReadInt16();
reader.ReadInt16(); // num of palette entries
reader.ReadInt32(); // offset to palette data
reader.ReadInt32(); // border colour
reader.ReadByte(); // min filter type
reader.ReadByte(); // mag filter type
reader.ReadInt16();
MipCount = reader.ReadByte();
reader.ReadByte();
reader.ReadInt16();
uint offsetToImageData = reader.ReadUInt32(); // offset to image data
//Lets set our method of decoding
PlatformSwizzle = PlatformSwizzle.Platform_Gamecube;
reader.Seek(offsetToImageData, System.IO.SeekOrigin.Begin);
int imageDataSize = RoundWidth((int)Width, (int)GetBlockWidth(Format)) *
RoundHeight((int)Height, (int)GetBlockHeight(Format)) * (int)GetBytesPerPixel(Format) >> 3;
ImageData = reader.ReadBytes(imageDataSize);
}
}
public byte[] Save()
{
return null;
}
public void Unload()
{
}
public byte[] ImageData { get; set; }
//A list of supported formats
//This gets used in the re encode option
public override TEX_FORMAT[] SupportedFormats
{
get
{
return new TEX_FORMAT[]
{
TEX_FORMAT.I4,
TEX_FORMAT.I8,
TEX_FORMAT.I4,
TEX_FORMAT.I8,
TEX_FORMAT.RGB565,
TEX_FORMAT.RGB5A3,
TEX_FORMAT.RGBA32,
TEX_FORMAT.C4,
TEX_FORMAT.C8,
TEX_FORMAT.C14X2,
TEX_FORMAT.CMPR,
};
}
}
public override bool CanEdit { get; set; } = false;
//This gets used in the image editor if the image gets edited
//This wll not be ran if "CanEdit" is set to false!
public override void SetImageData(System.Drawing.Bitmap bitmap, int ArrayLevel)
{
}
//Gets the raw image data in bytes
//Gets decoded automatically
public override byte[] GetImageData(int ArrayLevel = 0, int MipLevel = 0)
{
return ImageData;
}
//This is an event for when the tree is clicked on
//Load our editor
public override void OnClick(TreeView treeView)
{
//Here we check for an active editor and load a new one if not found
//This is used when a tree/object editor is used
ImageEditorBase editor = (ImageEditorBase)LibraryGUI.GetActiveContent(typeof(ImageEditorBase));
if (editor == null)
{
editor = new ImageEditorBase();
editor.Dock = DockStyle.Fill;
LibraryGUI.LoadEditor(editor);
}
//Load our image and any properties
//If you don't make a class for properties you can use a generic class provided in STGenericTexture
editor.LoadProperties(GenericProperties);
editor.LoadImage(this);
}
}
}

View file

@ -0,0 +1,162 @@
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using Toolbox.Library;
using Toolbox.Library.Forms;
using Toolbox.Library.IO;
namespace FirstPlugin
{
class TXE : STGenericTexture, IFileFormat, ISingleTextureIconLoader
{
public STGenericTexture IconTexture { get { return this; } }
public FileType FileType { get; set; } = FileType.Image;
public bool CanSave { get; set; }
public string[] Description { get; set; } = new string[] { "Pikmin 1 Proprietary Texture" };
public string[] Extension { get; set; } = new string[] { "*.txe" };
public string FileName { get; set; }
public string FilePath { get; set; }
//Stores compression info from being opened (done automaitcally)
public IFileInfo IFileInfo { get; set; }
//Check how the file wil be opened
public bool Identify(System.IO.Stream stream)
{
return Utils.HasExtension(FileName, ".txe");
}
//A Type list for custom types
//With this you can add in classes with IFileMenuExtension to add menus for this format
public Type[] Types
{
get
{
List<Type> types = new List<Type>();
return types.ToArray();
}
}
public static Dictionary<ushort, TEX_FORMAT> FormatsTXE = new Dictionary<ushort, TEX_FORMAT>()
{
[0] = TEX_FORMAT.RGB5A3,
[1] = TEX_FORMAT.CMPR,
[2] = TEX_FORMAT.RGB565,
[3] = TEX_FORMAT.I4,
[4] = TEX_FORMAT.I8,
[5] = TEX_FORMAT.IA4,
[6] = TEX_FORMAT.IA8,
[7] = TEX_FORMAT.RGBA32,
};
public void Load(System.IO.Stream stream)
{
Text = FileName;
//Set this if you want to save the file format
CanSave = false;
ImageKey = "Texture";
SelectedImageKey = "Texture";
//You can add a FileReader with Toolbox.Library.IO namespace
using (var reader = new FileReader(stream))
{
reader.SetByteOrder(true);
Width = reader.ReadUInt16();
Height = reader.ReadUInt16();
_ = reader.ReadInt16();
//Turn this format into a common format used by this tool
ushort texFormat = reader.ReadUInt16();
Format = FormatsTXE[texFormat];
//Lets set our method of decoding
PlatformSwizzle = PlatformSwizzle.Platform_Gamecube;
int imageDataSize = reader.ReadInt32();
reader.SeekBegin(32);
ImageData = reader.ReadBytes(imageDataSize);
Text = FileName;
}
}
public byte[] Save()
{
return null;
}
public void Unload()
{
}
public byte[] ImageData { get; set; }
//A list of supported formats
//This gets used in the re encode option
public override TEX_FORMAT[] SupportedFormats
{
get
{
return new TEX_FORMAT[]
{
TEX_FORMAT.I4,
TEX_FORMAT.I8,
TEX_FORMAT.IA4,
TEX_FORMAT.IA8,
TEX_FORMAT.RGB565,
TEX_FORMAT.RGB5A3,
TEX_FORMAT.RGBA32,
TEX_FORMAT.C4,
TEX_FORMAT.C8,
TEX_FORMAT.C14X2,
TEX_FORMAT.CMPR,
};
}
}
public override bool CanEdit { get; set; } = false;
//This gets used in the image editor if the image gets edited
//This wll not be ran if "CanEdit" is set to false!
public override void SetImageData(System.Drawing.Bitmap bitmap, int ArrayLevel)
{
}
//Gets the raw image data in bytes
//Gets decoded automatically
public override byte[] GetImageData(int ArrayLevel = 0, int MipLevel = 0)
{
return ImageData;
}
//This is an event for when the tree is clicked on
//Load our editor
public override void OnClick(TreeView treeView)
{
//Here we check for an active editor and load a new one if not found
//This is used when a tree/object editor is used
ImageEditorBase editor = (ImageEditorBase)LibraryGUI.GetActiveContent(typeof(ImageEditorBase));
if (editor == null)
{
editor = new ImageEditorBase();
editor.Dock = DockStyle.Fill;
LibraryGUI.LoadEditor(editor);
}
//Load our image and any properties
//If you don't make a class for properties you can use a generic class provided in STGenericTexture
editor.LoadProperties(GenericProperties);
editor.LoadImage(this);
}
}
}

View file

@ -275,10 +275,12 @@
<Compile Include="FileFormats\Font\BFTTF.cs" />
<Compile Include="FileFormats\HyruleWarriors\G1M.cs" />
<Compile Include="FileFormats\Message\MSBP.cs" />
<Compile Include="FileFormats\Texture\TXE.cs" />
<Compile Include="FileFormats\Texture\CTPK.cs" />
<Compile Include="FileFormats\Grezzo\CTXB.cs" />
<Compile Include="FileFormats\Texture\TPL.cs" />
<Compile Include="FileFormats\Rom\GCDisk.cs" />
<Compile Include="FileFormats\Texture\BTI.cs" />
<Compile Include="GL\BMD_Renderer.cs" />
<Compile Include="GL\CMB_Renderer.cs" />
<Compile Include="GL\GXToOpenGL.cs" />

View file

@ -287,6 +287,8 @@ namespace FirstPlugin
private Type[] LoadFileFormats()
{
List<Type> Formats = new List<Type>();
Formats.Add(typeof(BTI));
Formats.Add(typeof(TXE));
Formats.Add(typeof(SARC));
Formats.Add(typeof(BFRES));
Formats.Add(typeof(BCRES));

View file

@ -188,5 +188,7 @@ namespace Toolbox.Library
C8 = 247,
C14X2 = 248,
CMPR = 249,
RGB565 = 250,
RGB5A3 = 251
}
}

View file

@ -103,7 +103,7 @@ namespace Toolbox.Library
//
//Gets a list of surfaces given the start index of the array and the amount of arrays to obtain
//
public List<Surface> GetSurfaces(int ArrayIndexStart = 0, bool GetAllSurfaces = true, int GetSurfaceAmount = 1 )
public List<Surface> GetSurfaces(int ArrayIndexStart = 0, bool GetAllSurfaces = true, int GetSurfaceAmount = 1)
{
if (GetAllSurfaces)
GetSurfaceAmount = (int)ArrayCount;
@ -146,7 +146,8 @@ namespace Toolbox.Library
public uint MipCount
{
get { return mipCount; }
set {
set
{
if (value == 0)
mipCount = 1;
else if (value > 17)
@ -184,7 +185,7 @@ namespace Toolbox.Library
public RenderableTex RenderableTex { get; set; }
public abstract TEX_FORMAT[] SupportedFormats { get;}
public abstract TEX_FORMAT[] SupportedFormats { get; }
public static uint GetBytesPerPixel(TEX_FORMAT Format)
{
@ -212,7 +213,7 @@ namespace Toolbox.Library
private static readonly Dictionary<TEX_FORMAT, FormatInfo> FormatTable =
new Dictionary<TEX_FORMAT, FormatInfo>()
{
{
{ TEX_FORMAT.R32G32B32A32_FLOAT, new FormatInfo(16, 1, 1, 1, TargetBuffer.Color) },
{ TEX_FORMAT.R32G32B32A32_SINT, new FormatInfo(16, 1, 1, 1, TargetBuffer.Color) },
{ TEX_FORMAT.R32G32B32A32_UINT, new FormatInfo(16, 1, 1, 1, TargetBuffer.Color) },
@ -314,11 +315,24 @@ namespace Toolbox.Library
{ TEX_FORMAT.A4, new FormatInfo(4, 1, 1, 1, TargetBuffer.Color) },
{ TEX_FORMAT.A8_UNORM, new FormatInfo(8, 1, 1, 1, TargetBuffer.Color) },
{ TEX_FORMAT.D16_UNORM, new FormatInfo(2, 1, 1, 1, TargetBuffer.Depth) },
{ TEX_FORMAT.D24_UNORM_S8_UINT, new FormatInfo(4, 1, 1, 1, TargetBuffer.Depth) },
{ TEX_FORMAT.D32_FLOAT, new FormatInfo(4, 1, 1, 1, TargetBuffer.Depth) },
{ TEX_FORMAT.D32_FLOAT_S8X24_UINT, new FormatInfo(8, 1, 1, 1,TargetBuffer.DepthStencil) }
};
{ TEX_FORMAT.D16_UNORM, new FormatInfo(2, 1, 1, 1, TargetBuffer.Depth) },
{ TEX_FORMAT.D24_UNORM_S8_UINT, new FormatInfo(4, 1, 1, 1, TargetBuffer.Depth) },
{ TEX_FORMAT.D32_FLOAT, new FormatInfo(4, 1, 1, 1, TargetBuffer.Depth) },
{ TEX_FORMAT.D32_FLOAT_S8X24_UINT, new FormatInfo(8, 1, 1, 1, TargetBuffer.DepthStencil)},
{ TEX_FORMAT.I4, new FormatInfo(4, 8, 8, 1, TargetBuffer.Color) },
{ TEX_FORMAT.I8, new FormatInfo(8, 8, 4, 1, TargetBuffer.Color) },
{ TEX_FORMAT.IA4, new FormatInfo(8, 8, 4, 1, TargetBuffer.Color) },
{ TEX_FORMAT.IA8, new FormatInfo(16, 4, 4, 1, TargetBuffer.Color) },
{ TEX_FORMAT.RGB565, new FormatInfo(16, 4, 4, 1, TargetBuffer.Color) },
{ TEX_FORMAT.RGB5A3, new FormatInfo(16, 4, 4, 1, TargetBuffer.Color) },
{ TEX_FORMAT.RGBA32, new FormatInfo(32, 4, 4, 1, TargetBuffer.Color) },
{ TEX_FORMAT.C4, new FormatInfo(4, 8, 8, 1, TargetBuffer.Color) },
{ TEX_FORMAT.C8, new FormatInfo(8, 8, 4, 1, TargetBuffer.Color) },
{ TEX_FORMAT.C14X2, new FormatInfo(16, 4, 4, 1, TargetBuffer.Color) },
{ TEX_FORMAT.CMPR, new FormatInfo(4, 8, 8, 1, TargetBuffer.Color) }
};
/// <summary>
/// A Surface contains mip levels of compressed/uncompressed texture data
@ -328,7 +342,7 @@ namespace Toolbox.Library
public List<byte[]> mipmaps = new List<byte[]>();
}
public void CreateGenericTexture(uint width, uint height, List<Surface> surfaces, TEX_FORMAT format )
public void CreateGenericTexture(uint width, uint height, List<Surface> surfaces, TEX_FORMAT format)
{
Width = width;
Height = height;
@ -383,15 +397,16 @@ namespace Toolbox.Library
byte[] data = GetImageData(ArrayLevel, MipLevel);
byte[] paletteData = GetPaletteData();
if (data.Length == 0)
return new Bitmap(1,1);
return new Bitmap(1, 1);
try
{
if (data == null)
throw new Exception("Data is null!");
if (PlatformSwizzle == PlatformSwizzle.Platform_3DS && !IsCompressed(Format)) {
var Image = BitmapExtension.GetBitmap(ConvertBgraToRgba(CTR_3DS.DecodeBlock(data, (int)width, (int)height, Format)),
if (PlatformSwizzle == PlatformSwizzle.Platform_3DS && !IsCompressed(Format))
{
var Image = BitmapExtension.GetBitmap(ConvertBgraToRgba(CTR_3DS.DecodeBlock(data, (int)width, (int)height, Format)),
(int)width, (int)height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
Image.RotateFlip(RotateFlipType.RotateNoneFlipY); //It's upside down for some reason so flip it
return Image;
@ -506,11 +521,11 @@ namespace Toolbox.Library
/// <returns>Returns a byte array of decoded data. </returns>
public static byte[] DecodeBlock(byte[] data, uint Width, uint Height, TEX_FORMAT Format, byte[] paletteData, ImageParameters parameters, PALETTE_FORMAT PaletteFormat = PALETTE_FORMAT.None, PlatformSwizzle PlatformSwizzle = PlatformSwizzle.None)
{
if (data == null) throw new Exception($"Data is null!");
if (Format <= 0) throw new Exception($"Invalid Format!");
if (data == null) throw new Exception($"Data is null!");
if (Format <= 0) throw new Exception($"Invalid Format!");
if (data.Length <= 0) throw new Exception($"Data is empty!");
if (Width <= 0) throw new Exception($"Invalid width size {Width}!");
if (Height <= 0) throw new Exception($"Invalid height size {Height}!");
if (Width <= 0) throw new Exception($"Invalid width size {Width}!");
if (Height <= 0) throw new Exception($"Invalid height size {Height}!");
byte[] imageData = new byte[0];
bool DontSwapRG = false;
@ -552,7 +567,7 @@ namespace Toolbox.Library
public string DebugInfo()
{
return $"Texture Info:\n" +
$"Name: {Text}\n" +
$"Name: {Text}\n" +
$"Format: {Format}\n" +
$"Height: {Height}\n" +
$"Width: {Width}\n" +
@ -566,7 +581,7 @@ namespace Toolbox.Library
public uint GenerateMipCount(int Width, int Height)
{
return GenerateMipCount((uint)Width, (uint)Height);
return GenerateMipCount((uint)Width, (uint)Height);
}
public uint GenerateMipCount(uint Width, uint Height)
@ -686,7 +701,8 @@ namespace Toolbox.Library
}
}
public override void Export(string FileName) {
public override void Export(string FileName)
{
Export(FileName);
}
@ -712,7 +728,7 @@ namespace Toolbox.Library
if (sfd.ShowDialog() == DialogResult.OK)
{
Export(sfd.FileName, false, false, 0,0);
Export(sfd.FileName, false, false, 0, 0);
}
}
@ -757,7 +773,7 @@ namespace Toolbox.Library
public void SaveTGA(string FileName, bool ExportSurfaceLevel = false,
bool ExportMipMapLevel = false, int SurfaceLevel = 0, int MipLevel = 0)
{
}
public void SaveBitMap(string FileName, bool ExportSurfaceLevel = false,
bool ExportMipMapLevel = false, int SurfaceLevel = 0, int MipLevel = 0)
@ -773,7 +789,7 @@ namespace Toolbox.Library
{
progressBar.Task = "Select dialog option... ";
var result = MessageBox.Show("Multiple image surfaces found! Would you like to export them all?", "Image Exporter",
var result = MessageBox.Show("Multiple image surfaces found! Would you like to export them all?", "Image Exporter",
MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1);
if (result == DialogResult.Yes)
{
@ -798,7 +814,7 @@ namespace Toolbox.Library
return;
}
}
}
progressBar.Task = $"Decoding image {Text}... ";
progressBar.Value = 20;
@ -946,9 +962,9 @@ namespace Toolbox.Library
if (width > 1)
width /= 2;
if (height > 1)
height /= 2;
height /= 2;
}
return mipCount;
@ -996,7 +1012,7 @@ namespace Toolbox.Library
int pixel = 0;
for (int i = 0; i < bpp; i += 1)
pixel |= bytes[pos + i] << (8 * i);
comp = GetComponentsFromPixel(Format, pixel, comp);
NewImageData[pos_ + 3] = comp[compSel[3]];

Binary file not shown.

Binary file not shown.

View file

@ -27,9 +27,9 @@ namespace Toolbox.Library
case TextureFormats.I8: return TEX_FORMAT.I8;
case TextureFormats.IA4: return TEX_FORMAT.IA4;
case TextureFormats.IA8: return TEX_FORMAT.IA8;
case TextureFormats.RGB565: return TEX_FORMAT.R5G5B5_UNORM;
case TextureFormats.RGB5A3: return TEX_FORMAT.R5G5B5A3_UNORM;
case TextureFormats.RGBA32: return TEX_FORMAT.R32G32B32A32_FLOAT;
case TextureFormats.RGB565: return TEX_FORMAT.RGB565;
case TextureFormats.RGB5A3: return TEX_FORMAT.RGB5A3;
case TextureFormats.RGBA32: return TEX_FORMAT.RGBA32;
default:
throw new Exception("Unknown Format " + Format);
}
@ -72,9 +72,9 @@ namespace Toolbox.Library
case TEX_FORMAT.I8: return TextureFormats.I8;
case TEX_FORMAT.IA4: return TextureFormats.IA4;
case TEX_FORMAT.IA8: return TextureFormats.IA8;
case TEX_FORMAT.R5G5B5_UNORM: return TextureFormats.RGB565;
case TEX_FORMAT.R5G5B5A3_UNORM: return TextureFormats.RGB5A3;
case TEX_FORMAT.R32G32B32A32_FLOAT: return TextureFormats.RGBA32;
case TEX_FORMAT.RGB565: return TextureFormats.RGB565;
case TEX_FORMAT.RGB5A3: return TextureFormats.RGB5A3;
case TEX_FORMAT.RGBA32: return TextureFormats.RGBA32;
default:
throw new Exception("Unknown Format " + Format);
}

View file

@ -98,6 +98,7 @@
<HintPath>..\Toolbox\Lib\NAudio.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" />
<Reference Include="ObjectListView">
<HintPath>..\Toolbox\Lib\ObjectListView.dll</HintPath>
<Private>False</Private>

View file

@ -1 +1 @@
747948e0929dd8935549f97d0e91eb2d59336ea8
2dd7d0617dba111aa487a7da42ed4f5f18627a3f