mirror of
https://github.com/KillzXGaming/Switch-Toolbox
synced 2024-11-26 06:20:24 +00:00
Tons more DDS fixes from yesterday. RGB textures also aren't blue anymore.
This commit is contained in:
parent
a921e46a8f
commit
3a85f06ac7
15 changed files with 268 additions and 54 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -163,6 +163,12 @@ namespace Bfres.Structs
|
|||
if (setting.DataBlockOutput != null)
|
||||
{
|
||||
var surface = GTXSwizzle.CreateGx2Texture(setting.DataBlockOutput[0], setting);
|
||||
surface.compSel = new byte[4];
|
||||
surface.compSel[0] = (byte)setting.RedComp;
|
||||
surface.compSel[1] = (byte)setting.GreenComp;
|
||||
surface.compSel[2] = (byte)setting.BlueComp;
|
||||
surface.compSel[3] = (byte)setting.alphaRef;
|
||||
|
||||
var tex = FromGx2Surface(surface, setting.TexName);
|
||||
UpdateTex(tex);
|
||||
|
||||
|
@ -182,7 +188,12 @@ namespace Bfres.Structs
|
|||
}
|
||||
|
||||
public override void Replace(string FileName) {
|
||||
ReplaceTexture(FileName, Format);
|
||||
|
||||
//If the mipcount is originally 1 it's probably important so set it as default
|
||||
if (texture != null && texture.MipCount == 1)
|
||||
ReplaceTexture(FileName, Format, texture.MipCount);
|
||||
else
|
||||
ReplaceTexture(FileName, Format);
|
||||
}
|
||||
|
||||
public void ReplaceTexture(string FileName, TEX_FORMAT DefaultFormat = TEX_FORMAT.UNKNOWN, uint MipMapCount = 0, TEX_FORMAT[] SupportedFormats = null,
|
||||
|
@ -336,13 +347,20 @@ namespace Bfres.Structs
|
|||
}
|
||||
tex.Height = surf.height;
|
||||
tex.Width = surf.width;
|
||||
tex.Regs = new uint[5];
|
||||
tex.ArrayLength = 1;
|
||||
var channels = SetChannelsByFormat((GX2SurfaceFormat)surf.format);
|
||||
tex.CompSelR = channels[0];
|
||||
tex.CompSelG = channels[1];
|
||||
tex.CompSelB = channels[2];
|
||||
tex.CompSelA = channels[3];
|
||||
|
||||
tex.Regs = new uint[5];
|
||||
|
||||
if (surf.compSel.Length != 4)
|
||||
surf.compSel = new byte[] { 0, 1, 2, 3 };
|
||||
|
||||
//Set channels for settings and format
|
||||
tex.CompSelR = (GX2CompSel)surf.compSel[0];
|
||||
tex.CompSelG = (GX2CompSel)surf.compSel[1];
|
||||
tex.CompSelB = (GX2CompSel)surf.compSel[2];
|
||||
tex.CompSelA = (GX2CompSel)surf.compSel[3];
|
||||
SetChannelsByFormat((GX2SurfaceFormat)surf.format, tex);
|
||||
|
||||
tex.UserData = new ResDict<UserData>();
|
||||
return tex;
|
||||
}
|
||||
|
@ -590,7 +608,7 @@ namespace Bfres.Structs
|
|||
case GX2SurfaceFormat.TC_A1_B5_G5_R5_UNorm: return TEX_FORMAT.B5G5R5A1_UNORM;
|
||||
case GX2SurfaceFormat.TC_R4_G4_B4_A4_UNorm: return TEX_FORMAT.B4G4R4A4_UNORM;
|
||||
case GX2SurfaceFormat.TCS_R5_G6_B5_UNorm: return TEX_FORMAT.B5G6R5_UNORM;
|
||||
case GX2SurfaceFormat.TCS_R8_G8_B8_A8_SRGB: return TEX_FORMAT.R8G8B8A8_UNORM;
|
||||
case GX2SurfaceFormat.TCS_R8_G8_B8_A8_SRGB: return TEX_FORMAT.R8G8B8A8_UNORM_SRGB;
|
||||
case GX2SurfaceFormat.TCS_R8_G8_B8_A8_UNorm: return TEX_FORMAT.R8G8B8A8_UNORM;
|
||||
case GX2SurfaceFormat.TCS_R10_G10_B10_A2_UNorm: return TEX_FORMAT.R10G10B10A2_UNORM;
|
||||
case GX2SurfaceFormat.TC_R11_G11_B10_Float: return TEX_FORMAT.R11G11B10_FLOAT;
|
||||
|
@ -605,34 +623,25 @@ namespace Bfres.Structs
|
|||
throw new Exception($"Cannot convert format {GX2Format}");
|
||||
}
|
||||
}
|
||||
public static GX2CompSel[] SetChannelsByFormat(GX2SurfaceFormat Format)
|
||||
public static void SetChannelsByFormat(GX2SurfaceFormat Format, Texture tex)
|
||||
{
|
||||
GX2CompSel[] channels = new GX2CompSel[4];
|
||||
|
||||
switch (Format)
|
||||
{
|
||||
case GX2SurfaceFormat.T_BC5_UNorm:
|
||||
case GX2SurfaceFormat.T_BC5_SNorm:
|
||||
channels[0] = GX2CompSel.ChannelR;
|
||||
channels[1] = GX2CompSel.ChannelG;
|
||||
channels[2] = GX2CompSel.Always0;
|
||||
channels[3] = GX2CompSel.Always1;
|
||||
tex.CompSelR = GX2CompSel.ChannelR;
|
||||
tex.CompSelG = GX2CompSel.ChannelG;
|
||||
tex.CompSelB = GX2CompSel.Always0;
|
||||
tex.CompSelA = GX2CompSel.Always1;
|
||||
break;
|
||||
case GX2SurfaceFormat.T_BC4_SNorm:
|
||||
case GX2SurfaceFormat.T_BC4_UNorm:
|
||||
channels[0] = GX2CompSel.ChannelR;
|
||||
channels[1] = GX2CompSel.ChannelR;
|
||||
channels[2] = GX2CompSel.ChannelR;
|
||||
channels[3] = GX2CompSel.ChannelR;
|
||||
break;
|
||||
default:
|
||||
channels[0] = GX2CompSel.ChannelR;
|
||||
channels[1] = GX2CompSel.ChannelG;
|
||||
channels[2] = GX2CompSel.ChannelB;
|
||||
channels[3] = GX2CompSel.ChannelA;
|
||||
tex.CompSelR = GX2CompSel.ChannelR;
|
||||
tex.CompSelG = GX2CompSel.ChannelR;
|
||||
tex.CompSelB = GX2CompSel.ChannelR;
|
||||
tex.CompSelA = GX2CompSel.ChannelR;
|
||||
break;
|
||||
}
|
||||
return channels;
|
||||
}
|
||||
|
||||
public void Export(string FileName, bool ExportSurfaceLevel = false,
|
||||
|
|
|
@ -34,6 +34,11 @@ namespace FirstPlugin
|
|||
TEX_FORMAT.BC5_SNORM,
|
||||
TEX_FORMAT.R8G8B8A8_UNORM_SRGB,
|
||||
TEX_FORMAT.R8G8B8A8_UNORM,
|
||||
TEX_FORMAT.A8_UNORM,
|
||||
TEX_FORMAT.R8G8_UNORM,
|
||||
TEX_FORMAT.B5G6R5_UNORM,
|
||||
TEX_FORMAT.R10G10B10A2_UNORM,
|
||||
TEX_FORMAT.B4G4R4A4_UNORM,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -45,6 +50,7 @@ namespace FirstPlugin
|
|||
case TEX_FORMAT.A8_UNORM: return BFLIMFormat.L8_UNORM;
|
||||
case TEX_FORMAT.R8G8_UNORM: return BFLIMFormat.LA8;
|
||||
case TEX_FORMAT.B5G6R5_UNORM: return BFLIMFormat.RGB565;
|
||||
case TEX_FORMAT.B5G5R5A1_UNORM: return BFLIMFormat.RGB5A1;
|
||||
case TEX_FORMAT.R8G8B8A8_UNORM: return BFLIMFormat.RGBA8;
|
||||
case TEX_FORMAT.R8G8B8A8_UNORM_SRGB: return BFLIMFormat.RGBA8_SRGB;
|
||||
case TEX_FORMAT.R10G10B10A2_UNORM: return BFLIMFormat.RGB10A2_UNORM;
|
||||
|
|
|
@ -851,6 +851,7 @@ namespace FirstPlugin
|
|||
case TEX_FORMAT.R8_UNORM: return SurfaceFormat.R8_UNORM;
|
||||
case TEX_FORMAT.R8G8_UNORM: return SurfaceFormat.R8_G8_UNORM;
|
||||
case TEX_FORMAT.R32G8X24_FLOAT: return SurfaceFormat.R32_G8_X24_FLOAT;
|
||||
case TEX_FORMAT.B8G8R8X8_UNORM: return SurfaceFormat.B8_G8_R8_A8_UNORM; //Todo
|
||||
case TEX_FORMAT.ASTC_10x10_SRGB: return SurfaceFormat.ASTC_10x10_SRGB;
|
||||
case TEX_FORMAT.ASTC_10x10_UNORM: return SurfaceFormat.ASTC_10x10_UNORM;
|
||||
case TEX_FORMAT.ASTC_10x5_SRGB: return SurfaceFormat.ASTC_10x5_SRGB;
|
||||
|
|
|
@ -38,10 +38,10 @@ namespace FirstPlugin
|
|||
public SurfaceDim SurfaceDim = SurfaceDim.Dim2D;
|
||||
public TileMode TileMode = TileMode.Default;
|
||||
public Dim Dim = Dim.Dim2D;
|
||||
public ChannelType RedComp = ChannelType.Red;
|
||||
public ChannelType GreenComp = ChannelType.Green;
|
||||
public ChannelType BlueComp = ChannelType.Blue;
|
||||
public ChannelType AlphaComp = ChannelType.Alpha;
|
||||
public STChannelType RedComp = STChannelType.Red;
|
||||
public STChannelType GreenComp = STChannelType.Green;
|
||||
public STChannelType BlueComp = STChannelType.Blue;
|
||||
public STChannelType AlphaComp = STChannelType.Alpha;
|
||||
public TextureData textureData;
|
||||
public uint TextureLayout;
|
||||
public uint TextureLayout2 = 0x010007;
|
||||
|
@ -70,7 +70,12 @@ namespace FirstPlugin
|
|||
TexWidth = dds.header.width;
|
||||
TexHeight = dds.header.height;
|
||||
|
||||
var surfaces = DDS.GetArrayFaces(dds, dds.bdata, dds.ArrayCount);
|
||||
var surfaces = DDS.GetArrayFaces(dds, dds.ArrayCount);
|
||||
|
||||
RedComp = dds.RedChannel;
|
||||
GreenComp = dds.GreenChannel;
|
||||
BlueComp = dds.BlueChannel;
|
||||
AlphaComp = dds.AlphaChannel;
|
||||
|
||||
foreach (var surface in surfaces)
|
||||
DataBlockOutput.Add(Utils.CombineByteArray(surface.mipmaps.ToArray()));
|
||||
|
|
|
@ -30,7 +30,11 @@ namespace FirstPlugin
|
|||
public uint Swizzle = 0;
|
||||
public uint MipSwizzle = 0;
|
||||
|
||||
public GX2CompSel[] compSel = new GX2CompSel[4];
|
||||
public STChannelType RedComp = STChannelType.Red;
|
||||
public STChannelType GreenComp = STChannelType.Green;
|
||||
public STChannelType BlueComp = STChannelType.Blue;
|
||||
public STChannelType AlphaComp = STChannelType.Alpha;
|
||||
|
||||
public GX2SurfaceDim SurfaceDim = GX2SurfaceDim.Dim2D;
|
||||
public GX2AAMode AAMode = GX2AAMode.Mode1X;
|
||||
public float alphaRef = 0.5f;
|
||||
|
@ -57,6 +61,11 @@ namespace FirstPlugin
|
|||
}
|
||||
DataBlockOutput.Add(dds.bdata);
|
||||
|
||||
RedComp = dds.RedChannel;
|
||||
GreenComp = dds.GreenChannel;
|
||||
BlueComp = dds.BlueChannel;
|
||||
AlphaComp = dds.AlphaChannel;
|
||||
|
||||
Format = (GX2.GX2SurfaceFormat)FTEX.ConvertToGx2Format(dds.Format);;
|
||||
}
|
||||
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -531,24 +531,32 @@ namespace Switch_Toolbox.Library
|
|||
HasAlpha = true;
|
||||
}
|
||||
|
||||
Format = GetFormat();
|
||||
|
||||
if (!IsDX10 && !IsCompressed) {
|
||||
Format = GetUncompressedType(IsRGB, HasAlpha, HasLuminance, header.ddspf);
|
||||
}
|
||||
|
||||
reader.TemporarySeek((int)(4 + header.size + DX10HeaderSize), SeekOrigin.Begin);
|
||||
bdata = reader.ReadBytes((int)(reader.BaseStream.Length - reader.BaseStream.Position));
|
||||
|
||||
Format = GetFormat();
|
||||
Width = header.width;
|
||||
Height = header.height;
|
||||
MipCount = header.mipmapCount;
|
||||
|
||||
byte[] Components = new byte[4] { 0, 1, 2, 3 };
|
||||
|
||||
if (!IsDX10 && !IsCompressed) {
|
||||
Format = GetUncompressedType(this, Components, IsRGB, HasAlpha, HasLuminance, header.ddspf);
|
||||
}
|
||||
|
||||
RedChannel = (STChannelType)Components[0];
|
||||
GreenChannel = (STChannelType)Components[1];
|
||||
BlueChannel = (STChannelType)Components[2];
|
||||
AlphaChannel = (STChannelType)Components[3];
|
||||
|
||||
reader.Dispose();
|
||||
reader.Close();
|
||||
|
||||
|
||||
MipCount = header.mipmapCount;
|
||||
Width = header.width;
|
||||
Height = header.height;
|
||||
|
||||
}
|
||||
private TEX_FORMAT GetUncompressedType(bool IsRGB, bool HasAlpha, bool HasLuminance, Header.DDS_PixelFormat header)
|
||||
private TEX_FORMAT GetUncompressedType(DDS dds, byte[] Components, bool IsRGB, bool HasAlpha, bool HasLuminance, Header.DDS_PixelFormat header)
|
||||
{
|
||||
uint bpp = header.RGBBitCount;
|
||||
uint RedMask = header.RBitMask;
|
||||
|
@ -593,6 +601,7 @@ namespace Switch_Toolbox.Library
|
|||
{
|
||||
if (RedMask == R8G8B8_MASKS[0] && GreenMask == R8G8B8_MASKS[1] && BlueMask == R8G8B8_MASKS[2] && AlphaMask == R8G8B8_MASKS[3])
|
||||
{
|
||||
dds.bdata = ConvertToRgba(this, "RGB8", 3, new byte[4] { 2, 1, 0, 3 });
|
||||
return TEX_FORMAT.R8G8B8A8_UNORM;
|
||||
}
|
||||
else
|
||||
|
@ -608,14 +617,17 @@ namespace Switch_Toolbox.Library
|
|||
}
|
||||
else if (RedMask == X8B8G8R8_MASKS[0] && GreenMask == X8B8G8R8_MASKS[1] && BlueMask == X8B8G8R8_MASKS[2] && AlphaMask == X8B8G8R8_MASKS[3])
|
||||
{
|
||||
dds.bdata = ConvertToRgba(this, "RGB8X", 4, new byte[4] { 2, 1, 0, 3 });
|
||||
return TEX_FORMAT.B8G8R8X8_UNORM;
|
||||
}
|
||||
else if (RedMask == A8R8G8B8_MASKS[0] && GreenMask == A8R8G8B8_MASKS[1] && BlueMask == A8R8G8B8_MASKS[2] && AlphaMask == A8R8G8B8_MASKS[3])
|
||||
{
|
||||
dds.bdata = ConvertBgraToRgba(dds.bdata);
|
||||
return TEX_FORMAT.R8G8B8A8_UNORM;
|
||||
}
|
||||
else if (RedMask == X8R8G8B8_MASKS[0] && GreenMask == X8R8G8B8_MASKS[1] && BlueMask == X8R8G8B8_MASKS[2] && AlphaMask == X8R8G8B8_MASKS[3])
|
||||
{
|
||||
dds.bdata = ConvertToRgba(this, "RGB8X", 4, new byte[4] { 0, 1, 2, 3 });
|
||||
return TEX_FORMAT.B8G8R8X8_UNORM;
|
||||
}
|
||||
else
|
||||
|
@ -630,6 +642,118 @@ namespace Switch_Toolbox.Library
|
|||
}
|
||||
return TEX_FORMAT.UNKNOWN;
|
||||
}
|
||||
|
||||
private static byte[] ConvertRgb8ToRgbx8(byte[] bytes)
|
||||
{
|
||||
int size = bytes.Length / 3;
|
||||
byte[] NewData = new byte[size];
|
||||
|
||||
for (int i = 0; i < size; i ++)
|
||||
{
|
||||
NewData[4 * i + 0] = bytes[3 * i + 0];
|
||||
NewData[4 * i + 1] = bytes[3 * i + 1];
|
||||
NewData[4 * i + 2] = bytes[3 * i + 2];
|
||||
NewData[4 * i + 3] = 0xFF;
|
||||
}
|
||||
return NewData;
|
||||
}
|
||||
|
||||
//Thanks abood. Based on https://github.com/aboood40091/BNTX-Editor/blob/master/formConv.py
|
||||
private static byte[] ConvertToRgba(DDS dds, string Format, int bpp, byte[] compSel)
|
||||
{
|
||||
byte[] bytes = dds.bdata;
|
||||
|
||||
if (bytes == null)
|
||||
throw new Exception("Data block returned null. Make sure the parameters and image properties are correct!");
|
||||
|
||||
List<byte[]> mipmaps = new List<byte[]>();
|
||||
|
||||
uint Offset = 0;
|
||||
|
||||
for (byte a = 0; a < dds.ArrayCount; ++a)
|
||||
{
|
||||
for (byte m = 0; m < dds.MipCount; ++m)
|
||||
{
|
||||
uint MipWidth = Math.Max(1, dds.Width >> m);
|
||||
uint MipHeight = Math.Max(1, dds.Height >> m);
|
||||
|
||||
uint NewSize = (MipWidth * MipHeight) * 4;
|
||||
uint OldSize = (MipWidth * MipHeight) * (uint)bpp;
|
||||
|
||||
byte[] NewImageData = new byte[NewSize];
|
||||
mipmaps.Add(NewImageData);
|
||||
|
||||
byte[] comp = new byte[4] { 0, 0, 0, 0xFF };
|
||||
|
||||
for (int j = 0; j < MipHeight * MipWidth; j++)
|
||||
{
|
||||
var pos = Offset + (j * bpp);
|
||||
var pos_ = (j * 4);
|
||||
|
||||
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]];
|
||||
NewImageData[pos_ + 2] = comp[compSel[2]];
|
||||
NewImageData[pos_ + 1] = comp[compSel[1]];
|
||||
NewImageData[pos_ + 0] = comp[compSel[0]];
|
||||
}
|
||||
|
||||
Offset += OldSize;
|
||||
}
|
||||
}
|
||||
|
||||
return Utils.CombineByteArray(mipmaps.ToArray());
|
||||
}
|
||||
|
||||
private static byte[] GetComponentsFromPixel(string Format, int pixel, byte[] comp)
|
||||
{
|
||||
switch (Format)
|
||||
{
|
||||
case "RGB8X":
|
||||
comp[0] = (byte)(pixel & 0xFF);
|
||||
comp[1] = (byte)((pixel & 0xFF00) >> 8);
|
||||
comp[2] = (byte)((pixel & 0xFF0000) >> 16);
|
||||
comp[3] = (byte)(0xFF);
|
||||
break;
|
||||
case "RGB8":
|
||||
comp[0] = (byte)(pixel & 0xFF);
|
||||
comp[1] = (byte)((pixel & 0xFF00) >> 8);
|
||||
comp[2] = (byte)((pixel & 0xFF0000) >> 16);
|
||||
comp[3] = (byte)(0xFF);
|
||||
break;
|
||||
case "RGBA4":
|
||||
comp[0] = (byte)((pixel & 0xF) * 17);
|
||||
comp[1] = (byte)(((pixel & 0xF0) >> 4) * 17);
|
||||
comp[2] = (byte)(((pixel & 0xF00) >> 8) * 17);
|
||||
comp[3] = (byte)(((pixel & 0xF000) >> 12) * 17);
|
||||
break;
|
||||
case "RGBA5":
|
||||
comp[0] = (byte)(((pixel & 0xF800) >> 11) / 0x1F * 0xFF);
|
||||
comp[1] = (byte)(((pixel & 0x7E0) >> 5) / 0x3F * 0xFF);
|
||||
comp[2] = (byte)((pixel & 0x1F) / 0x1F * 0xFF);
|
||||
break;
|
||||
}
|
||||
|
||||
return comp;
|
||||
}
|
||||
|
||||
private static byte[] ConvertBgraToRgba(byte[] bytes)
|
||||
{
|
||||
if (bytes == null)
|
||||
throw new Exception("Data block returned null. Make sure the parameters and image properties are correct!");
|
||||
|
||||
for (int i = 0; i < bytes.Length; i += 4)
|
||||
{
|
||||
var temp = bytes[i];
|
||||
bytes[i] = bytes[i + 2];
|
||||
bytes[i + 2] = temp;
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
private void ReadDX10Header(BinaryDataReader reader)
|
||||
{
|
||||
DX10header = new DX10Header();
|
||||
|
@ -811,6 +935,7 @@ namespace Switch_Toolbox.Library
|
|||
var Surfaces = new List<STGenericTexture.Surface>();
|
||||
|
||||
uint formatSize = GetBytesPerPixel(dds.Format);
|
||||
|
||||
bool isBlock = dds.IsCompressed();
|
||||
if (dds.header.mipmapCount == 0)
|
||||
dds.header.mipmapCount = 1;
|
||||
|
|
|
@ -725,14 +725,5 @@ namespace Switch_Toolbox.Library
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] DecodeBC7(int X, int Y, int block)
|
||||
{
|
||||
byte[] result = null;
|
||||
|
||||
//Alright so BC7 decompression as multple modes
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -202,6 +202,8 @@ namespace Switch_Toolbox.Library
|
|||
{ TEX_FORMAT.R8G8_B8G8_UNORM, new FormatInfo(4, 1, 1, 1, TargetBuffer.Color) },
|
||||
{ TEX_FORMAT.B8G8R8X8_UNORM, new FormatInfo(4, 1, 1, 1, TargetBuffer.Color) },
|
||||
{ TEX_FORMAT.B5G5R5A1_UNORM, new FormatInfo(2, 1, 1, 1, TargetBuffer.Color) },
|
||||
{ TEX_FORMAT.B8G8R8A8_UNORM, new FormatInfo(4, 1, 1, 1, TargetBuffer.Color) },
|
||||
{ TEX_FORMAT.B8G8R8A8_UNORM_SRGB, new FormatInfo(4, 1, 1, 1, TargetBuffer.Color) },
|
||||
|
||||
{ TEX_FORMAT.R10G10B10A2_UINT, new FormatInfo(4, 1, 1, 1, TargetBuffer.Color) },
|
||||
{ TEX_FORMAT.R10G10B10A2_UNORM, new FormatInfo(4, 1, 1, 1, TargetBuffer.Color) },
|
||||
|
@ -457,8 +459,8 @@ namespace Switch_Toolbox.Library
|
|||
else
|
||||
{
|
||||
//If blue channel becomes first, do not swap them!
|
||||
if (Format.ToString().StartsWith("B") || Format == TEX_FORMAT.B5G6R5_UNORM)
|
||||
return DDSCompressor.DecodePixelBlock(data, (int)Width, (int)Height, (DDS.DXGI_FORMAT)Format);
|
||||
// if (Format.ToString().StartsWith("B") || Format == TEX_FORMAT.B5G6R5_UNORM)
|
||||
// return DDSCompressor.DecodePixelBlock(data, (int)Width, (int)Height, (DDS.DXGI_FORMAT)Format);
|
||||
if (IsAtscFormat(Format))
|
||||
return ConvertBgraToRgba(ASTCDecoder.DecodeToRGBA8888(data, (int)GetBlockWidth(Format), (int)GetBlockHeight(Format), 1, (int)Width, (int)Height, 1));
|
||||
else
|
||||
|
@ -812,6 +814,7 @@ namespace Switch_Toolbox.Library
|
|||
string extension = System.IO.Path.GetExtension(FileName);
|
||||
return FileName.Substring(0, FileName.Length - extension.Length);
|
||||
}
|
||||
|
||||
private static byte[] ConvertBgraToRgba(byte[] bytes)
|
||||
{
|
||||
if (bytes == null)
|
||||
|
@ -826,6 +829,71 @@ namespace Switch_Toolbox.Library
|
|||
return bytes;
|
||||
}
|
||||
|
||||
|
||||
private static byte[] ConvertBgraToRgba(byte[] bytes, string Format, int bpp, int width, int height, byte[] compSel)
|
||||
{
|
||||
if (bytes == null)
|
||||
throw new Exception("Data block returned null. Make sure the parameters and image properties are correct!");
|
||||
|
||||
int size = width * height * 4;
|
||||
byte[] NewImageData = new byte[size];
|
||||
|
||||
byte[] comp = new byte[6] { 0, 0xFF, 0, 0, 0, 0xFF };
|
||||
|
||||
for (int y = 0; y < height; y += 1)
|
||||
{
|
||||
for (int x = 0; x < width; x += 1)
|
||||
{
|
||||
var pos = (y * width + x) * bpp;
|
||||
var pos_ = (y * width + x) * 4;
|
||||
|
||||
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]];
|
||||
NewImageData[pos_ + 2] = comp[compSel[2]];
|
||||
NewImageData[pos_ + 1] = comp[compSel[1]];
|
||||
NewImageData[pos_ + 0] = comp[compSel[0]];
|
||||
}
|
||||
}
|
||||
return NewImageData;
|
||||
}
|
||||
|
||||
private static byte[] GetComponentsFromPixel(string Format, int pixel, byte[] comp)
|
||||
{
|
||||
switch (Format)
|
||||
{
|
||||
case "RGBX8":
|
||||
comp[2] = (byte)(pixel & 0xFF);
|
||||
comp[3] = (byte)((pixel & 0xFF00) >> 8);
|
||||
comp[4] = (byte)((pixel & 0xFF0000) >> 16);
|
||||
comp[5] = (byte)((pixel & 0xFF000000) >> 24);
|
||||
break;
|
||||
case "RGBA8":
|
||||
comp[2] = (byte)(pixel & 0xFF);
|
||||
comp[3] = (byte)((pixel & 0xFF00) >> 8);
|
||||
comp[4] = (byte)((pixel & 0xFF0000) >> 16);
|
||||
comp[5] = (byte)((pixel & 0xFF000000) >> 24);
|
||||
break;
|
||||
case "RGBA4":
|
||||
comp[2] = (byte)((pixel & 0xF) * 17);
|
||||
comp[3] = (byte)(((pixel & 0xF0) >> 4) * 17);
|
||||
comp[4] = (byte)(((pixel & 0xF00) >> 8) * 17);
|
||||
comp[5] = (byte)(((pixel & 0xF000) >> 12) * 17);
|
||||
break;
|
||||
case "RGBA5":
|
||||
comp[2] = (byte)(((pixel & 0xF800) >> 11) / 0x1F * 0xFF);
|
||||
comp[3] = (byte)(((pixel & 0x7E0) >> 5) / 0x3F * 0xFF);
|
||||
comp[4] = (byte)((pixel & 0x1F) / 0x1F * 0xFF);
|
||||
break;
|
||||
}
|
||||
|
||||
return comp;
|
||||
}
|
||||
|
||||
public override void Delete()
|
||||
{
|
||||
DisposeRenderable();
|
||||
|
|
|
@ -43,7 +43,7 @@ namespace Switch_Toolbox.Library
|
|||
|
||||
|
||||
public uint[] mipOffset;
|
||||
public byte[] compSel;
|
||||
public byte[] compSel = new byte[4] { 0,1,2,3};
|
||||
public uint[] texRegs;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue