Fix and improve Texture2D convert

This commit is contained in:
Perfare 2022-03-22 01:00:20 +08:00
parent 7d3a4a10fc
commit b1205808e2
4 changed files with 103 additions and 36 deletions

View File

@ -154,7 +154,8 @@ namespace AssetStudio
RGB565 = 7,
R16 = 9,
DXT1,
DXT5 = 12,
DXT3,
DXT5,
RGBA4444,
BGRA32,
RHalf,
@ -165,11 +166,11 @@ namespace AssetStudio
RGBAFloat,
YUY2,
RGB9e5Float,
BC4 = 26,
BC5,
BC6H = 24,
BC7,
DXT1Crunched = 28,
BC4,
BC5,
DXT1Crunched,
DXT5Crunched,
PVRTC_RGB2,
PVRTC_RGBA2,

View File

@ -759,7 +759,7 @@ namespace AssetStudioGUI
var image = m_Texture2D.ConvertToImage(true);
if (image != null)
{
var bitmap = new DirectBitmap(image.ConvertToBgra32Bytes(), m_Texture2D.m_Width, m_Texture2D.m_Height);
var bitmap = new DirectBitmap(image.ConvertToBytes(), m_Texture2D.m_Width, m_Texture2D.m_Height);
image.Dispose();
assetItem.InfoText = $"Width: {m_Texture2D.m_Width}\nHeight: {m_Texture2D.m_Height}\nFormat: {m_Texture2D.m_TextureFormat}";
switch (m_Texture2D.m_TextureSettings.m_FilterMode)
@ -1167,7 +1167,7 @@ namespace AssetStudioGUI
var image = m_Sprite.GetImage();
if (image != null)
{
var bitmap = new DirectBitmap(image.ConvertToBgra32Bytes(), image.Width, image.Height);
var bitmap = new DirectBitmap(image.ConvertToBytes(), image.Width, image.Height);
image.Dispose();
assetItem.InfoText = $"Width: {bitmap.Width}\nHeight: {bitmap.Height}\n";
PreviewTexture(bitmap);

View File

@ -43,7 +43,7 @@ namespace AssetStudio
return stream;
}
public static byte[] ConvertToBgra32Bytes(this Image<Bgra32> image)
public static byte[] ConvertToBytes<TPixel>(this Image<TPixel> image) where TPixel : unmanaged, IPixel<TPixel>
{
if (image.TryGetSinglePixelSpan(out var pixelSpan))
{

View File

@ -1,4 +1,5 @@
using System;
using System.Runtime.CompilerServices;
using Texture2DDecoder;
namespace AssetStudio
@ -11,6 +12,7 @@ namespace AssetStudio
private TextureFormat m_TextureFormat;
private int[] version;
private BuildTarget platform;
private int outPutSize;
public Texture2DConverter(Texture2D m_Texture2D)
{
@ -20,6 +22,7 @@ namespace AssetStudio
m_TextureFormat = m_Texture2D.m_TextureFormat;
version = m_Texture2D.version;
platform = m_Texture2D.platform;
outPutSize = m_Width * m_Height * 4;
}
public bool DecodeTexture2D(byte[] bytes)
@ -60,6 +63,8 @@ namespace AssetStudio
SwapBytesForXbox(buff);
flag = DecodeDXT1(buff, bytes);
break;
case TextureFormat.DXT3:
break;
case TextureFormat.DXT5: //test pass
SwapBytesForXbox(buff);
flag = DecodeDXT5(buff, bytes);
@ -94,18 +99,18 @@ namespace AssetStudio
case TextureFormat.RGB9e5Float: //test pass
flag = DecodeRGB9e5Float(buff, bytes);
break;
case TextureFormat.BC4: //test pass
flag = DecodeBC4(buff, bytes);
break;
case TextureFormat.BC5: //test pass
flag = DecodeBC5(buff, bytes);
break;
case TextureFormat.BC6H: //test pass
flag = DecodeBC6H(buff, bytes);
break;
case TextureFormat.BC7: //test pass
flag = DecodeBC7(buff, bytes);
break;
case TextureFormat.BC4: //test pass
flag = DecodeBC4(buff, bytes);
break;
case TextureFormat.BC5: //test pass
flag = DecodeBC5(buff, bytes);
break;
case TextureFormat.DXT1Crunched: //test pass
flag = DecodeDXT1Crunched(buff, bytes);
break;
@ -194,6 +199,15 @@ namespace AssetStudio
case TextureFormat.ETC2_RGBA8Crunched: //test pass
flag = DecodeETC2A8Crunched(buff, bytes);
break;
case TextureFormat.RG32: //test pass
flag = DecodeRG32(buff, bytes);
break;
case TextureFormat.RGB48: //test pass
flag = DecodeRGB48(buff, bytes);
break;
case TextureFormat.RGBA64: //test pass
flag = DecodeRGBA64(buff, bytes);
break;
}
BigArrayPool<byte>.Shared.Return(buff);
return flag;
@ -214,9 +228,10 @@ namespace AssetStudio
private bool DecodeAlpha8(byte[] image_data, byte[] buff)
{
var size = m_Width * m_Height;
var span = new Span<byte>(buff);
span.Fill(0xFF);
for (var i = 0; i < m_Width * m_Height; i++)
for (var i = 0; i < size; i++)
{
buff[i * 4 + 3] = image_data[i];
}
@ -225,8 +240,9 @@ namespace AssetStudio
private bool DecodeARGB4444(byte[] image_data, byte[] buff)
{
var size = m_Width * m_Height;
var pixelNew = new byte[4];
for (var i = 0; i < m_Width * m_Height; i++)
for (var i = 0; i < size; i++)
{
var pixelOldShort = BitConverter.ToUInt16(image_data, i * 2);
pixelNew[0] = (byte)(pixelOldShort & 0x000f);
@ -242,7 +258,8 @@ namespace AssetStudio
private bool DecodeRGB24(byte[] image_data, byte[] buff)
{
for (var i = 0; i < m_Width * m_Height; i++)
var size = m_Width * m_Height;
for (var i = 0; i < size; i++)
{
buff[i * 4] = image_data[i * 3 + 2];
buff[i * 4 + 1] = image_data[i * 3 + 1];
@ -254,7 +271,7 @@ namespace AssetStudio
private bool DecodeRGBA32(byte[] image_data, byte[] buff)
{
for (var i = 0; i < buff.Length; i += 4)
for (var i = 0; i < outPutSize; i += 4)
{
buff[i] = image_data[i + 2];
buff[i + 1] = image_data[i + 1];
@ -266,7 +283,7 @@ namespace AssetStudio
private bool DecodeARGB32(byte[] image_data, byte[] buff)
{
for (var i = 0; i < buff.Length; i += 4)
for (var i = 0; i < outPutSize; i += 4)
{
buff[i] = image_data[i + 3];
buff[i + 1] = image_data[i + 2];
@ -278,7 +295,8 @@ namespace AssetStudio
private bool DecodeRGB565(byte[] image_data, byte[] buff)
{
for (var i = 0; i < m_Width * m_Height; i++)
var size = m_Width * m_Height;
for (var i = 0; i < size; i++)
{
var p = BitConverter.ToUInt16(image_data, i * 2);
buff[i * 4] = (byte)((p << 3) | (p >> 2 & 7));
@ -291,11 +309,12 @@ namespace AssetStudio
private bool DecodeR16(byte[] image_data, byte[] buff)
{
for (var i = 0; i < m_Width * m_Height; i++)
var size = m_Width * m_Height;
for (var i = 0; i < size; i++)
{
buff[i * 4] = 0; //b
buff[i * 4 + 1] = 0; //g
buff[i * 4 + 2] = image_data[i * 2 + 1]; //r
buff[i * 4 + 2] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i * 2)); //r
buff[i * 4 + 3] = 255; //a
}
return true;
@ -313,8 +332,9 @@ namespace AssetStudio
private bool DecodeRGBA4444(byte[] image_data, byte[] buff)
{
var size = m_Width * m_Height;
var pixelNew = new byte[4];
for (var i = 0; i < m_Width * m_Height; i++)
for (var i = 0; i < size; i++)
{
var pixelOldShort = BitConverter.ToUInt16(image_data, i * 2);
pixelNew[0] = (byte)((pixelOldShort & 0x00f0) >> 4);
@ -330,7 +350,7 @@ namespace AssetStudio
private bool DecodeBGRA32(byte[] image_data, byte[] buff)
{
for (var i = 0; i < buff.Length; i += 4)
for (var i = 0; i < outPutSize; i += 4)
{
buff[i] = image_data[i];
buff[i + 1] = image_data[i + 1];
@ -342,7 +362,7 @@ namespace AssetStudio
private bool DecodeRHalf(byte[] image_data, byte[] buff)
{
for (var i = 0; i < buff.Length; i += 4)
for (var i = 0; i < outPutSize; i += 4)
{
buff[i] = 0;
buff[i + 1] = 0;
@ -354,7 +374,7 @@ namespace AssetStudio
private bool DecodeRGHalf(byte[] image_data, byte[] buff)
{
for (var i = 0; i < buff.Length; i += 4)
for (var i = 0; i < outPutSize; i += 4)
{
buff[i] = 0;
buff[i + 1] = (byte)Math.Round(Half.ToHalf(image_data, i + 2) * 255f);
@ -366,7 +386,7 @@ namespace AssetStudio
private bool DecodeRGBAHalf(byte[] image_data, byte[] buff)
{
for (var i = 0; i < buff.Length; i += 4)
for (var i = 0; i < outPutSize; i += 4)
{
buff[i] = (byte)Math.Round(Half.ToHalf(image_data, i * 2 + 4) * 255f);
buff[i + 1] = (byte)Math.Round(Half.ToHalf(image_data, i * 2 + 2) * 255f);
@ -378,7 +398,7 @@ namespace AssetStudio
private bool DecodeRFloat(byte[] image_data, byte[] buff)
{
for (var i = 0; i < buff.Length; i += 4)
for (var i = 0; i < outPutSize; i += 4)
{
buff[i] = 0;
buff[i + 1] = 0;
@ -390,7 +410,7 @@ namespace AssetStudio
private bool DecodeRGFloat(byte[] image_data, byte[] buff)
{
for (var i = 0; i < buff.Length; i += 4)
for (var i = 0; i < outPutSize; i += 4)
{
buff[i] = 0;
buff[i + 1] = (byte)Math.Round(BitConverter.ToSingle(image_data, i * 2 + 4) * 255f);
@ -402,7 +422,7 @@ namespace AssetStudio
private bool DecodeRGBAFloat(byte[] image_data, byte[] buff)
{
for (var i = 0; i < buff.Length; i += 4)
for (var i = 0; i < outPutSize; i += 4)
{
buff[i] = (byte)Math.Round(BitConverter.ToSingle(image_data, i * 4 + 8) * 255f);
buff[i + 1] = (byte)Math.Round(BitConverter.ToSingle(image_data, i * 4 + 4) * 255f);
@ -412,6 +432,7 @@ namespace AssetStudio
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static byte ClampByte(int x)
{
return (byte)(byte.MaxValue < x ? byte.MaxValue : (x > byte.MinValue ? x : byte.MinValue));
@ -449,7 +470,7 @@ namespace AssetStudio
private bool DecodeRGB9e5Float(byte[] image_data, byte[] buff)
{
for (var i = 0; i < buff.Length; i += 4)
for (var i = 0; i < outPutSize; i += 4)
{
var n = BitConverter.ToInt32(image_data, i);
var scale = n >> 27 & 0x1f;
@ -571,19 +592,21 @@ namespace AssetStudio
private bool DecodeRG16(byte[] image_data, byte[] buff)
{
for (var i = 0; i < m_Width * m_Height; i += 2)
var size = m_Width * m_Height;
for (var i = 0; i < size; i++)
{
buff[i * 2] = 0; //B
buff[i * 2 + 1] = image_data[i + 1];//G
buff[i * 2 + 2] = image_data[i];//R
buff[i * 2 + 3] = 255;//A
buff[i * 4] = 0; //B
buff[i * 4 + 1] = image_data[i * 2 + 1];//G
buff[i * 4 + 2] = image_data[i * 2];//R
buff[i * 4 + 3] = 255;//A
}
return true;
}
private bool DecodeR8(byte[] image_data, byte[] buff)
{
for (var i = 0; i < m_Width * m_Height; i++)
var size = m_Width * m_Height;
for (var i = 0; i < size; i++)
{
buff[i * 4] = 0; //B
buff[i * 4 + 1] = 0; //G
@ -617,6 +640,49 @@ namespace AssetStudio
return false;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte DownScaleFrom16BitTo8Bit(ushort component)
{
return (byte)(((component * 255) + 32895) >> 16);
}
private bool DecodeRG32(byte[] image_data, byte[] buff)
{
for (var i = 0; i < outPutSize; i += 4)
{
buff[i] = 0; //b
buff[i + 1] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i + 2)); //g
buff[i + 2] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i)); //r
buff[i + 3] = byte.MaxValue; //a
}
return true;
}
private bool DecodeRGB48(byte[] image_data, byte[] buff)
{
var size = m_Width * m_Height;
for (var i = 0; i < size; i++)
{
buff[i * 4] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i * 6 + 4)); //b
buff[i * 4 + 1] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i * 6 + 2)); //g
buff[i * 4 + 2] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i * 6)); //r
buff[i * 4 + 3] = byte.MaxValue; //a
}
return true;
}
private bool DecodeRGBA64(byte[] image_data, byte[] buff)
{
for (var i = 0; i < outPutSize; i += 4)
{
buff[i] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i * 2 + 4)); //b
buff[i + 1] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i * 2 + 2)); //g
buff[i + 2] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i * 2)); //r
buff[i + 3] = DownScaleFrom16BitTo8Bit(BitConverter.ToUInt16(image_data, i * 2 + 6)); //a
}
return true;
}
private bool UnpackCrunch(byte[] image_data, out byte[] result)
{
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 3) //2017.3 and up