diff --git a/AssetStudio/AssetStudio.csproj b/AssetStudio/AssetStudio.csproj
index e8d51d3..6b64c7d 100644
--- a/AssetStudio/AssetStudio.csproj
+++ b/AssetStudio/AssetStudio.csproj
@@ -8,6 +8,15 @@
Copyright © Perfare 2018-2021
+
+
+
+
+
+
+
+
+
none
false
diff --git a/AssetStudio/BigArrayPool.cs b/AssetStudio/BigArrayPool.cs
new file mode 100644
index 0000000..369e689
--- /dev/null
+++ b/AssetStudio/BigArrayPool.cs
@@ -0,0 +1,10 @@
+using System.Buffers;
+
+namespace AssetStudio
+{
+ public static class BigArrayPool
+ {
+ private static readonly ArrayPool s_shared = ArrayPool.Create(64 * 1024 * 1024, 3);
+ public static ArrayPool Shared => s_shared;
+ }
+}
diff --git a/AssetStudio/BundleFile.cs b/AssetStudio/BundleFile.cs
index 1e6ac8f..3352ea7 100644
--- a/AssetStudio/BundleFile.cs
+++ b/AssetStudio/BundleFile.cs
@@ -1,8 +1,6 @@
-using System;
-using System.Collections.Generic;
+using K4os.Compression.LZ4;
using System.IO;
using System.Linq;
-using Lz4;
namespace AssetStudio
{
@@ -221,30 +219,33 @@ namespace AssetStudio
{
blocksInfoBytes = reader.ReadBytes((int)m_Header.compressedBlocksInfoSize);
}
- var blocksInfoCompressedStream = new MemoryStream(blocksInfoBytes);
MemoryStream blocksInfoUncompresseddStream;
+ var uncompressedSize = m_Header.uncompressedBlocksInfoSize;
switch (m_Header.flags & 0x3F) //kArchiveCompressionTypeMask
{
default: //None
{
- blocksInfoUncompresseddStream = blocksInfoCompressedStream;
+ blocksInfoUncompresseddStream = new MemoryStream(blocksInfoBytes);
break;
}
case 1: //LZMA
{
- blocksInfoUncompresseddStream = new MemoryStream((int)(m_Header.uncompressedBlocksInfoSize));
- SevenZipHelper.StreamDecompress(blocksInfoCompressedStream, blocksInfoUncompresseddStream, m_Header.compressedBlocksInfoSize, m_Header.uncompressedBlocksInfoSize);
+ blocksInfoUncompresseddStream = new MemoryStream((int)(uncompressedSize));
+ using (var blocksInfoCompressedStream = new MemoryStream(blocksInfoBytes))
+ {
+ SevenZipHelper.StreamDecompress(blocksInfoCompressedStream, blocksInfoUncompresseddStream, m_Header.compressedBlocksInfoSize, m_Header.uncompressedBlocksInfoSize);
+ }
blocksInfoUncompresseddStream.Position = 0;
- blocksInfoCompressedStream.Close();
break;
}
case 2: //LZ4
case 3: //LZ4HC
{
- var uncompressedBytes = new byte[m_Header.uncompressedBlocksInfoSize];
- using (var decoder = new Lz4DecoderStream(blocksInfoCompressedStream))
+ var uncompressedBytes = new byte[uncompressedSize];
+ var numWrite = LZ4Codec.Decode(blocksInfoBytes, uncompressedBytes);
+ if (numWrite != uncompressedSize)
{
- decoder.Read(uncompressedBytes, 0, uncompressedBytes.Length);
+ throw new IOException($"Lz4 decompression error, write {numWrite} bytes but expected {uncompressedSize} bytes");
}
blocksInfoUncompresseddStream = new MemoryStream(uncompressedBytes);
break;
@@ -299,11 +300,19 @@ namespace AssetStudio
case 2: //LZ4
case 3: //LZ4HC
{
- var compressedStream = new MemoryStream(reader.ReadBytes((int)blockInfo.compressedSize));
- using (var lz4Stream = new Lz4DecoderStream(compressedStream))
+ var compressedSize = (int)blockInfo.compressedSize;
+ var compressedBytes = BigArrayPool.Shared.Rent(compressedSize);
+ reader.Read(compressedBytes, 0, compressedSize);
+ var uncompressedSize = (int)blockInfo.uncompressedSize;
+ var uncompressedBytes = BigArrayPool.Shared.Rent(uncompressedSize);
+ var numWrite = LZ4Codec.Decode(compressedBytes, 0, compressedSize, uncompressedBytes, 0, uncompressedSize);
+ if (numWrite != uncompressedSize)
{
- lz4Stream.CopyTo(blocksStream, blockInfo.uncompressedSize);
+ throw new IOException($"Lz4 decompression error, write {numWrite} bytes but expected {uncompressedSize} bytes");
}
+ blocksStream.Write(uncompressedBytes, 0, uncompressedSize);
+ BigArrayPool.Shared.Return(compressedBytes);
+ BigArrayPool.Shared.Return(uncompressedBytes);
break;
}
}
diff --git a/AssetStudio/Lz4DecoderStream.cs b/AssetStudio/Lz4DecoderStream.cs
deleted file mode 100644
index e767bb7..0000000
--- a/AssetStudio/Lz4DecoderStream.cs
+++ /dev/null
@@ -1,540 +0,0 @@
-#define CHECK_ARGS
-#define CHECK_EOF
-//#define LOCAL_SHADOW
-
-using System;
-using System.IO;
-
-namespace Lz4
-{
- public class Lz4DecoderStream : Stream
- {
- public Lz4DecoderStream(Stream input, long inputLength = long.MaxValue)
- {
- Reset(input, inputLength);
- }
-
- private void Reset(Stream input, long inputLength = long.MaxValue)
- {
- this.inputLength = inputLength;
- this.input = input;
-
- phase = DecodePhase.ReadToken;
-
- decodeBufferPos = 0;
-
- litLen = 0;
- matLen = 0;
- matDst = 0;
-
- inBufPos = DecBufLen;
- inBufEnd = DecBufLen;
- }
-
- protected override void Dispose(bool disposing)
- {
- try
- {
- if (disposing && input != null)
- {
- input.Close();
- }
- input = null;
- decodeBuffer = null;
- }
- finally
- {
- base.Dispose(disposing);
- }
- }
-
- private long inputLength;
- private Stream input;
-
- //because we might not be able to match back across invocations,
- //we have to keep the last window's worth of bytes around for reuse
- //we use a circular buffer for this - every time we write into this
- //buffer, we also write the same into our output buffer
-
- private const int DecBufLen = 0x10000;
- private const int DecBufMask = 0xFFFF;
-
- private const int InBufLen = 128;
-
- private byte[] decodeBuffer = new byte[DecBufLen + InBufLen];
- private int decodeBufferPos, inBufPos, inBufEnd;
-
- //we keep track of which phase we're in so that we can jump right back
- //into the correct part of decoding
-
- private DecodePhase phase;
-
- private enum DecodePhase
- {
- ReadToken,
- ReadExLiteralLength,
- CopyLiteral,
- ReadOffset,
- ReadExMatchLength,
- CopyMatch,
- }
-
- //state within interruptable phases and across phase boundaries is
- //kept here - again, so that we can punt out and restart freely
-
- private int litLen, matLen, matDst;
-
- public override int Read(byte[] buffer, int offset, int count)
- {
-#if CHECK_ARGS
- if (buffer == null)
- throw new ArgumentNullException("buffer");
- if (offset < 0 || count < 0 || buffer.Length - count < offset)
- throw new ArgumentOutOfRangeException();
-
- if (input == null)
- throw new InvalidOperationException();
-#endif
- int nRead, nToRead = count;
-
- var decBuf = decodeBuffer;
-
- //the stringy gotos are obnoxious, but their purpose is to
- //make it *blindingly* obvious how the state machine transitions
- //back and forth as it reads - remember, we can yield out of
- //this routine in several places, and we must be able to re-enter
- //and pick up where we left off!
-
-#if LOCAL_SHADOW
- var phase = this.phase;
- var inBufPos = this.inBufPos;
- var inBufEnd = this.inBufEnd;
-#endif
- switch (phase)
- {
- case DecodePhase.ReadToken:
- goto readToken;
-
- case DecodePhase.ReadExLiteralLength:
- goto readExLiteralLength;
-
- case DecodePhase.CopyLiteral:
- goto copyLiteral;
-
- case DecodePhase.ReadOffset:
- goto readOffset;
-
- case DecodePhase.ReadExMatchLength:
- goto readExMatchLength;
-
- case DecodePhase.CopyMatch:
- goto copyMatch;
- }
-
- readToken:
- int tok;
- if (inBufPos < inBufEnd)
- {
- tok = decBuf[inBufPos++];
- }
- else
- {
-#if LOCAL_SHADOW
- this.inBufPos = inBufPos;
-#endif
-
- tok = ReadByteCore();
-#if LOCAL_SHADOW
- inBufPos = this.inBufPos;
- inBufEnd = this.inBufEnd;
-#endif
-#if CHECK_EOF
- if (tok == -1)
- goto finish;
-#endif
- }
-
- litLen = tok >> 4;
- matLen = (tok & 0xF) + 4;
-
- switch (litLen)
- {
- case 0:
- phase = DecodePhase.ReadOffset;
- goto readOffset;
-
- case 0xF:
- phase = DecodePhase.ReadExLiteralLength;
- goto readExLiteralLength;
-
- default:
- phase = DecodePhase.CopyLiteral;
- goto copyLiteral;
- }
-
- readExLiteralLength:
- int exLitLen;
- if (inBufPos < inBufEnd)
- {
- exLitLen = decBuf[inBufPos++];
- }
- else
- {
-#if LOCAL_SHADOW
- this.inBufPos = inBufPos;
-#endif
- exLitLen = ReadByteCore();
-#if LOCAL_SHADOW
- inBufPos = this.inBufPos;
- inBufEnd = this.inBufEnd;
-#endif
-
-#if CHECK_EOF
- if (exLitLen == -1)
- goto finish;
-#endif
- }
-
- litLen += exLitLen;
- if (exLitLen == 255)
- goto readExLiteralLength;
-
- phase = DecodePhase.CopyLiteral;
- goto copyLiteral;
-
- copyLiteral:
- int nReadLit = litLen < nToRead ? litLen : nToRead;
- if (nReadLit != 0)
- {
- if (inBufPos + nReadLit <= inBufEnd)
- {
- int ofs = offset;
-
- for (int c = nReadLit; c-- != 0;)
- buffer[ofs++] = decBuf[inBufPos++];
-
- nRead = nReadLit;
- }
- else
- {
-#if LOCAL_SHADOW
- this.inBufPos = inBufPos;
-#endif
- nRead = ReadCore(buffer, offset, nReadLit);
-#if LOCAL_SHADOW
- inBufPos = this.inBufPos;
- inBufEnd = this.inBufEnd;
-#endif
-#if CHECK_EOF
- if (nRead == 0)
- goto finish;
-#endif
- }
-
- offset += nRead;
- nToRead -= nRead;
-
- litLen -= nRead;
-
- if (litLen != 0)
- goto copyLiteral;
- }
-
- if (nToRead == 0)
- goto finish;
-
- phase = DecodePhase.ReadOffset;
- goto readOffset;
-
- readOffset:
- if (inBufPos + 1 < inBufEnd)
- {
- matDst = (decBuf[inBufPos + 1] << 8) | decBuf[inBufPos];
- inBufPos += 2;
- }
- else
- {
-#if LOCAL_SHADOW
- this.inBufPos = inBufPos;
-#endif
- matDst = ReadOffsetCore();
-#if LOCAL_SHADOW
- inBufPos = this.inBufPos;
- inBufEnd = this.inBufEnd;
-#endif
-#if CHECK_EOF
- if (matDst == -1)
- goto finish;
-#endif
- }
-
- if (matLen == 15 + 4)
- {
- phase = DecodePhase.ReadExMatchLength;
- goto readExMatchLength;
- }
- else
- {
- phase = DecodePhase.CopyMatch;
- goto copyMatch;
- }
-
- readExMatchLength:
- int exMatLen;
- if (inBufPos < inBufEnd)
- {
- exMatLen = decBuf[inBufPos++];
- }
- else
- {
-#if LOCAL_SHADOW
- this.inBufPos = inBufPos;
-#endif
- exMatLen = ReadByteCore();
-#if LOCAL_SHADOW
- inBufPos = this.inBufPos;
- inBufEnd = this.inBufEnd;
-#endif
-#if CHECK_EOF
- if (exMatLen == -1)
- goto finish;
-#endif
- }
-
- matLen += exMatLen;
- if (exMatLen == 255)
- goto readExMatchLength;
-
- phase = DecodePhase.CopyMatch;
- goto copyMatch;
-
- copyMatch:
- int nCpyMat = matLen < nToRead ? matLen : nToRead;
- if (nCpyMat != 0)
- {
- nRead = count - nToRead;
-
- int bufDst = matDst - nRead;
- if (bufDst > 0)
- {
- //offset is fairly far back, we need to pull from the buffer
-
- int bufSrc = decodeBufferPos - bufDst;
- if (bufSrc < 0)
- bufSrc += DecBufLen;
- int bufCnt = bufDst < nCpyMat ? bufDst : nCpyMat;
-
- for (int c = bufCnt; c-- != 0;)
- buffer[offset++] = decBuf[bufSrc++ & DecBufMask];
- }
- else
- {
- bufDst = 0;
- }
-
- int sOfs = offset - matDst;
- for (int i = bufDst; i < nCpyMat; i++)
- buffer[offset++] = buffer[sOfs++];
-
- nToRead -= nCpyMat;
- matLen -= nCpyMat;
- }
-
- if (nToRead == 0)
- goto finish;
-
- phase = DecodePhase.ReadToken;
- goto readToken;
-
- finish:
- nRead = count - nToRead;
-
- int nToBuf = nRead < DecBufLen ? nRead : DecBufLen;
- int repPos = offset - nToBuf;
-
- if (nToBuf == DecBufLen)
- {
- Buffer.BlockCopy(buffer, repPos, decBuf, 0, DecBufLen);
- decodeBufferPos = 0;
- }
- else
- {
- int decPos = decodeBufferPos;
-
- while (nToBuf-- != 0)
- decBuf[decPos++ & DecBufMask] = buffer[repPos++];
-
- decodeBufferPos = decPos & DecBufMask;
- }
-
-#if LOCAL_SHADOW
- this.phase = phase;
- this.inBufPos = inBufPos;
-#endif
- return nRead;
- }
-
- private int ReadByteCore()
- {
- var buf = decodeBuffer;
-
- if (inBufPos == inBufEnd)
- {
- int nRead = input.Read(buf, DecBufLen,
- InBufLen < inputLength ? InBufLen : (int)inputLength);
-
-#if CHECK_EOF
- if (nRead == 0)
- return -1;
-#endif
-
- inputLength -= nRead;
-
- inBufPos = DecBufLen;
- inBufEnd = DecBufLen + nRead;
- }
-
- return buf[inBufPos++];
- }
-
- private int ReadOffsetCore()
- {
- var buf = decodeBuffer;
-
- if (inBufPos == inBufEnd)
- {
- int nRead = input.Read(buf, DecBufLen,
- InBufLen < inputLength ? InBufLen : (int)inputLength);
-
-#if CHECK_EOF
- if (nRead == 0)
- return -1;
-#endif
-
- inputLength -= nRead;
-
- inBufPos = DecBufLen;
- inBufEnd = DecBufLen + nRead;
- }
-
- if (inBufEnd - inBufPos == 1)
- {
- buf[DecBufLen] = buf[inBufPos];
-
- int nRead = input.Read(buf, DecBufLen + 1,
- InBufLen - 1 < inputLength ? InBufLen - 1 : (int)inputLength);
-
-#if CHECK_EOF
- if (nRead == 0)
- {
- inBufPos = DecBufLen;
- inBufEnd = DecBufLen + 1;
-
- return -1;
- }
-#endif
-
- inputLength -= nRead;
-
- inBufPos = DecBufLen;
- inBufEnd = DecBufLen + nRead + 1;
- }
-
- int ret = (buf[inBufPos + 1] << 8) | buf[inBufPos];
- inBufPos += 2;
-
- return ret;
- }
-
- private int ReadCore(byte[] buffer, int offset, int count)
- {
- int nToRead = count;
-
- var buf = decodeBuffer;
- int inBufLen = inBufEnd - inBufPos;
-
- int fromBuf = nToRead < inBufLen ? nToRead : inBufLen;
- if (fromBuf != 0)
- {
- var bufPos = inBufPos;
-
- for (int c = fromBuf; c-- != 0;)
- buffer[offset++] = buf[bufPos++];
-
- inBufPos = bufPos;
- nToRead -= fromBuf;
- }
-
- if (nToRead != 0)
- {
- int nRead;
-
- if (nToRead >= InBufLen)
- {
- nRead = input.Read(buffer, offset,
- nToRead < inputLength ? nToRead : (int)inputLength);
- nToRead -= nRead;
- }
- else
- {
- nRead = input.Read(buf, DecBufLen,
- InBufLen < inputLength ? InBufLen : (int)inputLength);
-
- inBufPos = DecBufLen;
- inBufEnd = DecBufLen + nRead;
-
- fromBuf = nToRead < nRead ? nToRead : nRead;
-
- var bufPos = inBufPos;
-
- for (int c = fromBuf; c-- != 0;)
- buffer[offset++] = buf[bufPos++];
-
- inBufPos = bufPos;
- nToRead -= fromBuf;
- }
-
- inputLength -= nRead;
- }
-
- return count - nToRead;
- }
-
- #region Stream internals
-
- public override bool CanRead => true;
-
- public override bool CanSeek => false;
-
- public override bool CanWrite => false;
-
- public override void Flush()
- {
- }
-
- public override long Length => throw new NotSupportedException();
-
- public override long Position
- {
- get => throw new NotSupportedException();
- set => throw new NotSupportedException();
- }
-
- public override long Seek(long offset, SeekOrigin origin)
- {
- throw new NotSupportedException();
- }
-
- public override void SetLength(long value)
- {
- throw new NotSupportedException();
- }
-
- public override void Write(byte[] buffer, int offset, int count)
- {
- throw new NotSupportedException();
- }
-
- #endregion
- }
-}
diff --git a/AssetStudio/ResourceReader.cs b/AssetStudio/ResourceReader.cs
index fc294cd..a717111 100644
--- a/AssetStudio/ResourceReader.cs
+++ b/AssetStudio/ResourceReader.cs
@@ -11,6 +11,8 @@ namespace AssetStudio
private long size;
private BinaryReader reader;
+ public int Size { get => (int)size; }
+
public ResourceReader(string path, SerializedFile assetsFile, long offset, long size)
{
needSearch = true;
@@ -69,6 +71,13 @@ namespace AssetStudio
return binaryReader.ReadBytes((int)size);
}
+ public void GetData(byte[] buff)
+ {
+ var binaryReader = GetReader();
+ binaryReader.BaseStream.Position = offset;
+ binaryReader.Read(buff, 0, (int)size);
+ }
+
public void WriteData(string path)
{
var binaryReader = GetReader();
diff --git a/AssetStudioGUI/AssetStudioGUIForm.cs b/AssetStudioGUI/AssetStudioGUIForm.cs
index fe11359..219ad7f 100644
--- a/AssetStudioGUI/AssetStudioGUIForm.cs
+++ b/AssetStudioGUI/AssetStudioGUIForm.cs
@@ -802,7 +802,7 @@ namespace AssetStudioGUI
var bmpData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
var bytes = new byte[bitmap.Width * bitmap.Height * 4];
Marshal.Copy(bmpData.Scan0, bytes, 0, bytes.Length);
- for (int i = 0; i < bmpData.Height; i++)
+ Parallel.For(0, bmpData.Height, i =>
{
int offset = Math.Abs(bmpData.Stride) * i;
for (int j = 0; j < bmpData.Width; j++)
@@ -813,7 +813,7 @@ namespace AssetStudioGUI
bytes[offset + 3] = textureChannels[3] ? bytes[offset + 3] : byte.MaxValue;
offset += 4;
}
- }
+ });
Marshal.Copy(bytes, 0, bmpData.Scan0, bytes.Length);
bitmap.UnlockBits(bmpData);
}
@@ -1246,6 +1246,7 @@ namespace AssetStudioGUI
classesListView.Groups.Clear();
previewPanel.BackgroundImage = Properties.Resources.preview;
imageTexture?.Dispose();
+ imageTexture = null;
previewPanel.BackgroundImageLayout = ImageLayout.Center;
assetInfoLabel.Visible = false;
assetInfoLabel.Text = null;
diff --git a/AssetStudioUtility/ShaderConverter.cs b/AssetStudioUtility/ShaderConverter.cs
index 8aa0474..e2385bc 100644
--- a/AssetStudioUtility/ShaderConverter.cs
+++ b/AssetStudioUtility/ShaderConverter.cs
@@ -1,10 +1,10 @@
-using System;
+using K4os.Compression.LZ4;
+using System;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
-using Lz4;
namespace AssetStudio
{
@@ -15,10 +15,7 @@ namespace AssetStudio
if (shader.m_SubProgramBlob != null) //5.3 - 5.4
{
var decompressedBytes = new byte[shader.decompressedSize];
- using (var decoder = new Lz4DecoderStream(new MemoryStream(shader.m_SubProgramBlob)))
- {
- decoder.Read(decompressedBytes, 0, (int)shader.decompressedSize);
- }
+ LZ4Codec.Decode(shader.m_SubProgramBlob, decompressedBytes);
using (var blobReader = new BinaryReader(new MemoryStream(decompressedBytes)))
{
var program = new ShaderProgram(blobReader, shader.version);
@@ -42,10 +39,7 @@ namespace AssetStudio
var compressedBytes = new byte[shader.compressedLengths[i]];
Buffer.BlockCopy(shader.compressedBlob, (int)shader.offsets[i], compressedBytes, 0, (int)shader.compressedLengths[i]);
var decompressedBytes = new byte[shader.decompressedLengths[i]];
- using (var decoder = new Lz4DecoderStream(new MemoryStream(compressedBytes)))
- {
- decoder.Read(decompressedBytes, 0, (int)shader.decompressedLengths[i]);
- }
+ LZ4Codec.Decode(compressedBytes, decompressedBytes);
using (var blobReader = new BinaryReader(new MemoryStream(decompressedBytes)))
{
shaderPrograms[i] = new ShaderProgram(blobReader, shader.version);
diff --git a/AssetStudioUtility/Texture2DConverter.cs b/AssetStudioUtility/Texture2DConverter.cs
index a9610ba..dfaf14d 100644
--- a/AssetStudioUtility/Texture2DConverter.cs
+++ b/AssetStudioUtility/Texture2DConverter.cs
@@ -1,23 +1,20 @@
using System;
-using System.Linq;
using Texture2DDecoder;
namespace AssetStudio
{
public class Texture2DConverter
{
+ private ResourceReader reader;
private int m_Width;
private int m_Height;
private TextureFormat m_TextureFormat;
- private int image_data_size;
- private byte[] image_data;
private int[] version;
private BuildTarget platform;
public Texture2DConverter(Texture2D m_Texture2D)
{
- image_data = m_Texture2D.image_data.GetData();
- image_data_size = image_data.Length;
+ reader = m_Texture2D.image_data;
m_Width = m_Texture2D.m_Width;
m_Height = m_Texture2D.m_Height;
m_TextureFormat = m_Texture2D.m_TextureFormat;
@@ -25,193 +22,188 @@ namespace AssetStudio
platform = m_Texture2D.platform;
}
- public byte[] DecodeTexture2D()
+ public bool DecodeTexture2D(byte[] bytes)
{
- byte[] bytes = null;
+ if (reader.Size == 0 || m_Width == 0 || m_Height == 0)
+ {
+ return false;
+ }
+ var flag = false;
+ var buff = BigArrayPool.Shared.Rent(reader.Size);
+ reader.GetData(buff);
switch (m_TextureFormat)
{
case TextureFormat.Alpha8: //test pass
- bytes = DecodeAlpha8();
+ flag = DecodeAlpha8(buff, bytes);
break;
case TextureFormat.ARGB4444: //test pass
- SwapBytesForXbox();
- bytes = DecodeARGB4444();
+ SwapBytesForXbox(buff);
+ flag = DecodeARGB4444(buff, bytes);
break;
case TextureFormat.RGB24: //test pass
- bytes = DecodeRGB24();
+ flag = DecodeRGB24(buff, bytes);
break;
case TextureFormat.RGBA32: //test pass
- bytes = DecodeRGBA32();
+ flag = DecodeRGBA32(buff, bytes);
break;
case TextureFormat.ARGB32: //test pass
- bytes = DecodeARGB32();
+ flag = DecodeARGB32(buff, bytes);
break;
case TextureFormat.RGB565: //test pass
- SwapBytesForXbox();
- bytes = DecodeRGB565();
+ SwapBytesForXbox(buff);
+ flag = DecodeRGB565(buff, bytes);
break;
case TextureFormat.R16: //test pass
- bytes = DecodeR16();
+ flag = DecodeR16(buff, bytes);
break;
case TextureFormat.DXT1: //test pass
- SwapBytesForXbox();
- bytes = DecodeDXT1();
+ SwapBytesForXbox(buff);
+ flag = DecodeDXT1(buff, bytes);
break;
case TextureFormat.DXT5: //test pass
- SwapBytesForXbox();
- bytes = DecodeDXT5();
+ SwapBytesForXbox(buff);
+ flag = DecodeDXT5(buff, bytes);
break;
case TextureFormat.RGBA4444: //test pass
- bytes = DecodeRGBA4444();
+ flag = DecodeRGBA4444(buff, bytes);
break;
case TextureFormat.BGRA32: //test pass
- bytes = DecodeBGRA32();
+ flag = DecodeBGRA32(buff, bytes);
break;
case TextureFormat.RHalf:
- bytes = DecodeRHalf();
+ flag = DecodeRHalf(buff, bytes);
break;
case TextureFormat.RGHalf:
- bytes = DecodeRGHalf();
+ flag = DecodeRGHalf(buff, bytes);
break;
case TextureFormat.RGBAHalf: //test pass
- bytes = DecodeRGBAHalf();
+ flag = DecodeRGBAHalf(buff, bytes);
break;
case TextureFormat.RFloat:
- bytes = DecodeRFloat();
+ flag = DecodeRFloat(buff, bytes);
break;
case TextureFormat.RGFloat:
- bytes = DecodeRGFloat();
+ flag = DecodeRGFloat(buff, bytes);
break;
case TextureFormat.RGBAFloat:
- bytes = DecodeRGBAFloat();
+ flag = DecodeRGBAFloat(buff, bytes);
break;
case TextureFormat.YUY2: //test pass
- bytes = DecodeYUY2();
+ flag = DecodeYUY2(buff, bytes);
break;
case TextureFormat.RGB9e5Float: //test pass
- bytes = DecodeRGB9e5Float();
+ flag = DecodeRGB9e5Float(buff, bytes);
break;
case TextureFormat.BC4: //test pass
- bytes = DecodeBC4();
+ flag = DecodeBC4(buff, bytes);
break;
case TextureFormat.BC5: //test pass
- bytes = DecodeBC5();
+ flag = DecodeBC5(buff, bytes);
break;
case TextureFormat.BC6H: //test pass
- bytes = DecodeBC6H();
+ flag = DecodeBC6H(buff, bytes);
break;
case TextureFormat.BC7: //test pass
- bytes = DecodeBC7();
+ flag = DecodeBC7(buff, bytes);
break;
case TextureFormat.DXT1Crunched: //test pass
- if (UnpackCrunch())
- {
- bytes = DecodeDXT1();
- }
+ flag = DecodeDXT1Crunched(buff, bytes);
break;
case TextureFormat.DXT5Crunched: //test pass
- if (UnpackCrunch())
- {
- bytes = DecodeDXT5();
- }
+ flag = DecodeDXT5Crunched(buff, bytes);
break;
case TextureFormat.PVRTC_RGB2: //test pass
case TextureFormat.PVRTC_RGBA2: //test pass
- bytes = DecodePVRTC(true);
+ flag = DecodePVRTC(buff, bytes, true);
break;
case TextureFormat.PVRTC_RGB4: //test pass
case TextureFormat.PVRTC_RGBA4: //test pass
- bytes = DecodePVRTC(false);
+ flag = DecodePVRTC(buff, bytes, false);
break;
case TextureFormat.ETC_RGB4: //test pass
case TextureFormat.ETC_RGB4_3DS:
- bytes = DecodeETC1();
+ flag = DecodeETC1(buff, bytes);
break;
case TextureFormat.ATC_RGB4: //test pass
- bytes = DecodeATCRGB4();
+ flag = DecodeATCRGB4(buff, bytes);
break;
case TextureFormat.ATC_RGBA8: //test pass
- bytes = DecodeATCRGBA8();
+ flag = DecodeATCRGBA8(buff, bytes);
break;
case TextureFormat.EAC_R: //test pass
- bytes = DecodeEACR();
+ flag = DecodeEACR(buff, bytes);
break;
case TextureFormat.EAC_R_SIGNED:
- bytes = DecodeEACRSigned();
+ flag = DecodeEACRSigned(buff, bytes);
break;
case TextureFormat.EAC_RG: //test pass
- bytes = DecodeEACRG();
+ flag = DecodeEACRG(buff, bytes);
break;
case TextureFormat.EAC_RG_SIGNED:
- bytes = DecodeEACRGSigned();
+ flag = DecodeEACRGSigned(buff, bytes);
break;
case TextureFormat.ETC2_RGB: //test pass
- bytes = DecodeETC2();
+ flag = DecodeETC2(buff, bytes);
break;
case TextureFormat.ETC2_RGBA1: //test pass
- bytes = DecodeETC2A1();
+ flag = DecodeETC2A1(buff, bytes);
break;
case TextureFormat.ETC2_RGBA8: //test pass
case TextureFormat.ETC_RGBA8_3DS:
- bytes = DecodeETC2A8();
+ flag = DecodeETC2A8(buff, bytes);
break;
case TextureFormat.ASTC_RGB_4x4: //test pass
case TextureFormat.ASTC_RGBA_4x4: //test pass
case TextureFormat.ASTC_HDR_4x4: //test pass
- bytes = DecodeASTC(4);
+ flag = DecodeASTC(buff, bytes, 4);
break;
case TextureFormat.ASTC_RGB_5x5: //test pass
case TextureFormat.ASTC_RGBA_5x5: //test pass
case TextureFormat.ASTC_HDR_5x5: //test pass
- bytes = DecodeASTC(5);
+ flag = DecodeASTC(buff, bytes, 5);
break;
case TextureFormat.ASTC_RGB_6x6: //test pass
case TextureFormat.ASTC_RGBA_6x6: //test pass
case TextureFormat.ASTC_HDR_6x6: //test pass
- bytes = DecodeASTC(6);
+ flag = DecodeASTC(buff, bytes, 6);
break;
case TextureFormat.ASTC_RGB_8x8: //test pass
case TextureFormat.ASTC_RGBA_8x8: //test pass
case TextureFormat.ASTC_HDR_8x8: //test pass
- bytes = DecodeASTC(8);
+ flag = DecodeASTC(buff, bytes, 8);
break;
case TextureFormat.ASTC_RGB_10x10: //test pass
case TextureFormat.ASTC_RGBA_10x10: //test pass
case TextureFormat.ASTC_HDR_10x10: //test pass
- bytes = DecodeASTC(10);
+ flag = DecodeASTC(buff, bytes, 10);
break;
case TextureFormat.ASTC_RGB_12x12: //test pass
case TextureFormat.ASTC_RGBA_12x12: //test pass
case TextureFormat.ASTC_HDR_12x12: //test pass
- bytes = DecodeASTC(12);
+ flag = DecodeASTC(buff, bytes, 12);
break;
case TextureFormat.RG16: //test pass
- bytes = DecodeRG16();
+ flag = DecodeRG16(buff, bytes);
break;
case TextureFormat.R8: //test pass
- bytes = DecodeR8();
+ flag = DecodeR8(buff, bytes);
break;
case TextureFormat.ETC_RGB4Crunched: //test pass
- if (UnpackCrunch())
- {
- bytes = DecodeETC1();
- }
+ flag = DecodeETC1Crunched(buff, bytes);
break;
case TextureFormat.ETC2_RGBA8Crunched: //test pass
- if (UnpackCrunch())
- {
- bytes = DecodeETC2A8();
- }
+ flag = DecodeETC2A8Crunched(buff, bytes);
break;
}
- return bytes;
+ BigArrayPool.Shared.Return(buff);
+ return flag;
}
- private void SwapBytesForXbox()
+ private void SwapBytesForXbox(byte[] image_data)
{
if (platform == BuildTarget.XBOX360)
{
- for (var i = 0; i < image_data_size / 2; i++)
+ for (var i = 0; i < image_data.Length / 2; i++)
{
var b = image_data[i * 2];
image_data[i * 2] = image_data[i * 2 + 1];
@@ -220,22 +212,22 @@ namespace AssetStudio
}
}
- private byte[] DecodeAlpha8()
+ private bool DecodeAlpha8(byte[] image_data, byte[] buff)
{
- var buff = Enumerable.Repeat(0xFF, m_Width * m_Height * 4).ToArray();
+ var span = new Span(buff);
+ span.Fill(0xFF);
for (var i = 0; i < m_Width * m_Height; i++)
{
buff[i * 4 + 3] = image_data[i];
}
- return buff;
+ return true;
}
- private byte[] DecodeARGB4444()
+ private bool DecodeARGB4444(byte[] image_data, byte[] buff)
{
- var buff = new byte[m_Width * m_Height * 4];
+ var pixelNew = new byte[4];
for (var i = 0; i < m_Width * m_Height; i++)
{
- var pixelNew = new byte[4];
var pixelOldShort = BitConverter.ToUInt16(image_data, i * 2);
pixelNew[0] = (byte)(pixelOldShort & 0x000f);
pixelNew[1] = (byte)((pixelOldShort & 0x00f0) >> 4);
@@ -245,12 +237,11 @@ namespace AssetStudio
pixelNew[j] = (byte)((pixelNew[j] << 4) | pixelNew[j]);
pixelNew.CopyTo(buff, i * 4);
}
- return buff;
+ return true;
}
- private byte[] DecodeRGB24()
+ private bool DecodeRGB24(byte[] image_data, byte[] buff)
{
- var buff = new byte[m_Width * m_Height * 4];
for (var i = 0; i < m_Width * m_Height; i++)
{
buff[i * 4] = image_data[i * 3 + 2];
@@ -258,12 +249,11 @@ namespace AssetStudio
buff[i * 4 + 2] = image_data[i * 3 + 0];
buff[i * 4 + 3] = 255;
}
- return buff;
+ return true;
}
- private byte[] DecodeRGBA32()
+ private bool DecodeRGBA32(byte[] image_data, byte[] buff)
{
- var buff = new byte[m_Width * m_Height * 4];
for (var i = 0; i < buff.Length; i += 4)
{
buff[i] = image_data[i + 2];
@@ -271,12 +261,11 @@ namespace AssetStudio
buff[i + 2] = image_data[i + 0];
buff[i + 3] = image_data[i + 3];
}
- return buff;
+ return true;
}
- private byte[] DecodeARGB32()
+ private bool DecodeARGB32(byte[] image_data, byte[] buff)
{
- var buff = new byte[m_Width * m_Height * 4];
for (var i = 0; i < buff.Length; i += 4)
{
buff[i] = image_data[i + 3];
@@ -284,12 +273,11 @@ namespace AssetStudio
buff[i + 2] = image_data[i + 1];
buff[i + 3] = image_data[i + 0];
}
- return buff;
+ return true;
}
- private byte[] DecodeRGB565()
+ private bool DecodeRGB565(byte[] image_data, byte[] buff)
{
- var buff = new byte[m_Width * m_Height * 4];
for (var i = 0; i < m_Width * m_Height; i++)
{
var p = BitConverter.ToUInt16(image_data, i * 2);
@@ -298,46 +286,36 @@ namespace AssetStudio
buff[i * 4 + 2] = (byte)((p >> 8 & 0xf8) | (p >> 13));
buff[i * 4 + 3] = 255;
}
- return buff;
+ return true;
}
- private byte[] DecodeR16()
+ private bool DecodeR16(byte[] image_data, byte[] buff)
{
- var buff = new byte[m_Width * m_Height * 4];
for (var i = 0; i < m_Width * m_Height; 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 + 3] = 255; //a
}
- return buff;
+ return true;
}
- private byte[] DecodeDXT1()
+ private bool DecodeDXT1(byte[] image_data, byte[] buff)
{
- var buff = new byte[m_Width * m_Height * 4];
- if (!TextureDecoder.DecodeDXT1(image_data, m_Width, m_Height, buff))
- {
- return null;
- }
- return buff;
+ return TextureDecoder.DecodeDXT1(image_data, m_Width, m_Height, buff);
}
- private byte[] DecodeDXT5()
+ private bool DecodeDXT5(byte[] image_data, byte[] buff)
{
- var buff = new byte[m_Width * m_Height * 4];
- if (!TextureDecoder.DecodeDXT5(image_data, m_Width, m_Height, buff))
- {
- return null;
- }
- return buff;
+ return TextureDecoder.DecodeDXT5(image_data, m_Width, m_Height, buff);
}
- private byte[] DecodeRGBA4444()
+ private bool DecodeRGBA4444(byte[] image_data, byte[] buff)
{
- var buff = new byte[m_Width * m_Height * 4];
+ var pixelNew = new byte[4];
for (var i = 0; i < m_Width * m_Height; i++)
{
- var pixelNew = new byte[4];
var pixelOldShort = BitConverter.ToUInt16(image_data, i * 2);
pixelNew[0] = (byte)((pixelOldShort & 0x00f0) >> 4);
pixelNew[1] = (byte)((pixelOldShort & 0x0f00) >> 8);
@@ -347,12 +325,11 @@ namespace AssetStudio
pixelNew[j] = (byte)((pixelNew[j] << 4) | pixelNew[j]);
pixelNew.CopyTo(buff, i * 4);
}
- return buff;
+ return true;
}
- private byte[] DecodeBGRA32()
+ private bool DecodeBGRA32(byte[] image_data, byte[] buff)
{
- var buff = new byte[m_Width * m_Height * 4];
for (var i = 0; i < buff.Length; i += 4)
{
buff[i] = image_data[i];
@@ -360,12 +337,11 @@ namespace AssetStudio
buff[i + 2] = image_data[i + 2];
buff[i + 3] = image_data[i + 3];
}
- return buff;
+ return true;
}
- private byte[] DecodeRHalf()
+ private bool DecodeRHalf(byte[] image_data, byte[] buff)
{
- var buff = new byte[m_Width * m_Height * 4];
for (var i = 0; i < buff.Length; i += 4)
{
buff[i] = 0;
@@ -373,12 +349,11 @@ namespace AssetStudio
buff[i + 2] = (byte)Math.Round(Half.ToHalf(image_data, i / 2) * 255f);
buff[i + 3] = 255;
}
- return buff;
+ return true;
}
- private byte[] DecodeRGHalf()
+ private bool DecodeRGHalf(byte[] image_data, byte[] buff)
{
- var buff = new byte[m_Width * m_Height * 4];
for (var i = 0; i < buff.Length; i += 4)
{
buff[i] = 0;
@@ -386,12 +361,11 @@ namespace AssetStudio
buff[i + 2] = (byte)Math.Round(Half.ToHalf(image_data, i) * 255f);
buff[i + 3] = 255;
}
- return buff;
+ return true;
}
- private byte[] DecodeRGBAHalf()
+ private bool DecodeRGBAHalf(byte[] image_data, byte[] buff)
{
- var buff = new byte[m_Width * m_Height * 4];
for (var i = 0; i < buff.Length; i += 4)
{
buff[i] = (byte)Math.Round(Half.ToHalf(image_data, i * 2 + 4) * 255f);
@@ -399,12 +373,11 @@ namespace AssetStudio
buff[i + 2] = (byte)Math.Round(Half.ToHalf(image_data, i * 2) * 255f);
buff[i + 3] = (byte)Math.Round(Half.ToHalf(image_data, i * 2 + 6) * 255f);
}
- return buff;
+ return true;
}
- private byte[] DecodeRFloat()
+ private bool DecodeRFloat(byte[] image_data, byte[] buff)
{
- var buff = new byte[m_Width * m_Height * 4];
for (var i = 0; i < buff.Length; i += 4)
{
buff[i] = 0;
@@ -412,12 +385,11 @@ namespace AssetStudio
buff[i + 2] = (byte)Math.Round(BitConverter.ToSingle(image_data, i) * 255f);
buff[i + 3] = 255;
}
- return buff;
+ return true;
}
- private byte[] DecodeRGFloat()
+ private bool DecodeRGFloat(byte[] image_data, byte[] buff)
{
- var buff = new byte[m_Width * m_Height * 4];
for (var i = 0; i < buff.Length; i += 4)
{
buff[i] = 0;
@@ -425,12 +397,11 @@ namespace AssetStudio
buff[i + 2] = (byte)Math.Round(BitConverter.ToSingle(image_data, i * 2) * 255f);
buff[i + 3] = 255;
}
- return buff;
+ return true;
}
- private byte[] DecodeRGBAFloat()
+ private bool DecodeRGBAFloat(byte[] image_data, byte[] buff)
{
- var buff = new byte[m_Width * m_Height * 4];
for (var i = 0; i < buff.Length; i += 4)
{
buff[i] = (byte)Math.Round(BitConverter.ToSingle(image_data, i * 4 + 8) * 255f);
@@ -438,7 +409,7 @@ namespace AssetStudio
buff[i + 2] = (byte)Math.Round(BitConverter.ToSingle(image_data, i * 4) * 255f);
buff[i + 3] = (byte)Math.Round(BitConverter.ToSingle(image_data, i * 4 + 12) * 255f);
}
- return buff;
+ return true;
}
private static byte ClampByte(int x)
@@ -446,9 +417,8 @@ namespace AssetStudio
return (byte)(byte.MaxValue < x ? byte.MaxValue : (x > byte.MinValue ? x : byte.MinValue));
}
- private byte[] DecodeYUY2()
+ private bool DecodeYUY2(byte[] image_data, byte[] buff)
{
- var buff = new byte[m_Width * m_Height * 4];
int p = 0;
int o = 0;
int halfWidth = m_Width / 2;
@@ -474,12 +444,11 @@ namespace AssetStudio
buff[o++] = 255;
}
}
- return buff;
+ return true;
}
- private byte[] DecodeRGB9e5Float()
+ private bool DecodeRGB9e5Float(byte[] image_data, byte[] buff)
{
- var buff = new byte[m_Width * m_Height * 4];
for (var i = 0; i < buff.Length; i += 4)
{
var n = BitConverter.ToInt32(image_data, i);
@@ -493,195 +462,163 @@ namespace AssetStudio
buff[i + 2] = (byte)Math.Round(r * scalef * 255f);
buff[i + 3] = 255;
}
- return buff;
+ return true;
}
- private byte[] DecodeBC4()
+ private bool DecodeBC4(byte[] image_data, byte[] buff)
{
- var buff = new byte[m_Width * m_Height * 4];
- if (!TextureDecoder.DecodeBC4(image_data, m_Width, m_Height, buff))
+ return TextureDecoder.DecodeBC4(image_data, m_Width, m_Height, buff);
+ }
+
+ private bool DecodeBC5(byte[] image_data, byte[] buff)
+ {
+ return TextureDecoder.DecodeBC5(image_data, m_Width, m_Height, buff);
+ }
+
+ private bool DecodeBC6H(byte[] image_data, byte[] buff)
+ {
+ return TextureDecoder.DecodeBC6(image_data, m_Width, m_Height, buff);
+ }
+
+ private bool DecodeBC7(byte[] image_data, byte[] buff)
+ {
+ return TextureDecoder.DecodeBC7(image_data, m_Width, m_Height, buff);
+ }
+
+ private bool DecodeDXT1Crunched(byte[] image_data, byte[] buff)
+ {
+ if (UnpackCrunch(image_data, out var result))
{
- return null;
+ if (DecodeDXT1(result, buff))
+ {
+ return true;
+ }
}
- return buff;
+ return false;
}
- private byte[] DecodeBC5()
+ private bool DecodeDXT5Crunched(byte[] image_data, byte[] buff)
{
- var buff = new byte[m_Width * m_Height * 4];
- if (!TextureDecoder.DecodeBC5(image_data, m_Width, m_Height, buff))
+ if (UnpackCrunch(image_data, out var result))
{
- return null;
+ if (DecodeDXT5(result, buff))
+ {
+ return true;
+ }
}
- return buff;
+ return false;
}
- private byte[] DecodeBC6H()
+ private bool DecodePVRTC(byte[] image_data, byte[] buff, bool is2bpp)
{
- var buff = new byte[m_Width * m_Height * 4];
- if (!TextureDecoder.DecodeBC6(image_data, m_Width, m_Height, buff))
- {
- return null;
- }
- return buff;
+ return TextureDecoder.DecodePVRTC(image_data, m_Width, m_Height, buff, is2bpp);
}
- private byte[] DecodeBC7()
+ private bool DecodeETC1(byte[] image_data, byte[] buff)
{
- var buff = new byte[m_Width * m_Height * 4];
- if (!TextureDecoder.DecodeBC7(image_data, m_Width, m_Height, buff))
- {
- return null;
- }
- return buff;
+ return TextureDecoder.DecodeETC1(image_data, m_Width, m_Height, buff);
}
- private byte[] DecodePVRTC(bool is2bpp)
+ private bool DecodeATCRGB4(byte[] image_data, byte[] buff)
{
- var buff = new byte[m_Width * m_Height * 4];
- if (!TextureDecoder.DecodePVRTC(image_data, m_Width, m_Height, buff, is2bpp))
- {
- return null;
- }
- return buff;
+ return TextureDecoder.DecodeATCRGB4(image_data, m_Width, m_Height, buff);
}
- private byte[] DecodeETC1()
+ private bool DecodeATCRGBA8(byte[] image_data, byte[] buff)
{
- var buff = new byte[m_Width * m_Height * 4];
- if (!TextureDecoder.DecodeETC1(image_data, m_Width, m_Height, buff))
- {
- return null;
- }
- return buff;
+ return TextureDecoder.DecodeATCRGBA8(image_data, m_Width, m_Height, buff);
}
- private byte[] DecodeATCRGB4()
+ private bool DecodeEACR(byte[] image_data, byte[] buff)
{
- var buff = new byte[m_Width * m_Height * 4];
- if (!TextureDecoder.DecodeATCRGB4(image_data, m_Width, m_Height, buff))
- {
- return null;
- }
- return buff;
+ return TextureDecoder.DecodeEACR(image_data, m_Width, m_Height, buff);
}
- private byte[] DecodeATCRGBA8()
+ private bool DecodeEACRSigned(byte[] image_data, byte[] buff)
{
- var buff = new byte[m_Width * m_Height * 4];
- if (!TextureDecoder.DecodeATCRGBA8(image_data, m_Width, m_Height, buff))
- {
- return null;
- }
- return buff;
+ return TextureDecoder.DecodeEACRSigned(image_data, m_Width, m_Height, buff);
}
- private byte[] DecodeEACR()
+ private bool DecodeEACRG(byte[] image_data, byte[] buff)
{
- var buff = new byte[m_Width * m_Height * 4];
- if (!TextureDecoder.DecodeEACR(image_data, m_Width, m_Height, buff))
- {
- return null;
- }
- return buff;
+ return TextureDecoder.DecodeEACRG(image_data, m_Width, m_Height, buff);
}
- private byte[] DecodeEACRSigned()
+ private bool DecodeEACRGSigned(byte[] image_data, byte[] buff)
{
- var buff = new byte[m_Width * m_Height * 4];
- if (!TextureDecoder.DecodeEACRSigned(image_data, m_Width, m_Height, buff))
- {
- return null;
- }
- return buff;
+ return TextureDecoder.DecodeEACRGSigned(image_data, m_Width, m_Height, buff);
}
- private byte[] DecodeEACRG()
+ private bool DecodeETC2(byte[] image_data, byte[] buff)
{
- var buff = new byte[m_Width * m_Height * 4];
- if (!TextureDecoder.DecodeEACRG(image_data, m_Width, m_Height, buff))
- {
- return null;
- }
- return buff;
+ return TextureDecoder.DecodeETC2(image_data, m_Width, m_Height, buff);
}
- private byte[] DecodeEACRGSigned()
+ private bool DecodeETC2A1(byte[] image_data, byte[] buff)
{
- var buff = new byte[m_Width * m_Height * 4];
- if (!TextureDecoder.DecodeEACRGSigned(image_data, m_Width, m_Height, buff))
- {
- return null;
- }
- return buff;
+ return TextureDecoder.DecodeETC2A1(image_data, m_Width, m_Height, buff);
}
- private byte[] DecodeETC2()
+ private bool DecodeETC2A8(byte[] image_data, byte[] buff)
{
- var buff = new byte[m_Width * m_Height * 4];
- if (!TextureDecoder.DecodeETC2(image_data, m_Width, m_Height, buff))
- {
- return null;
- }
- return buff;
+ return TextureDecoder.DecodeETC2A8(image_data, m_Width, m_Height, buff);
}
- private byte[] DecodeETC2A1()
+ private bool DecodeASTC(byte[] image_data, byte[] buff, int blocksize)
{
- var buff = new byte[m_Width * m_Height * 4];
- if (!TextureDecoder.DecodeETC2A1(image_data, m_Width, m_Height, buff))
- {
- return null;
- }
- return buff;
+ return TextureDecoder.DecodeASTC(image_data, m_Width, m_Height, blocksize, blocksize, buff);
}
- private byte[] DecodeETC2A8()
+ private bool DecodeRG16(byte[] image_data, byte[] buff)
{
- var buff = new byte[m_Width * m_Height * 4];
- if (!TextureDecoder.DecodeETC2A8(image_data, m_Width, m_Height, buff))
- {
- return null;
- }
- return buff;
- }
-
- private byte[] DecodeASTC(int blocksize)
- {
- var buff = new byte[m_Width * m_Height * 4];
- if (!TextureDecoder.DecodeASTC(image_data, m_Width, m_Height, blocksize, blocksize, buff))
- {
- return null;
- }
- return buff;
- }
-
- private byte[] DecodeRG16()
- {
- var buff = new byte[m_Width * m_Height * 4];
for (var i = 0; i < m_Width * m_Height; i += 2)
{
+ 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
}
- return buff;
+ return true;
}
- private byte[] DecodeR8()
+ private bool DecodeR8(byte[] image_data, byte[] buff)
{
- var buff = new byte[m_Width * m_Height * 4];
for (var i = 0; i < m_Width * m_Height; i++)
{
+ buff[i * 4] = 0; //B
+ buff[i * 4 + 1] = 0; //G
buff[i * 4 + 2] = image_data[i];//R
buff[i * 4 + 3] = 255;//A
}
- return buff;
+ return true;
}
- private bool UnpackCrunch()
+ private bool DecodeETC1Crunched(byte[] image_data, byte[] buff)
+ {
+ if (UnpackCrunch(image_data, out var result))
+ {
+ if (DecodeETC1(result, buff))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private bool DecodeETC2A8Crunched(byte[] image_data, byte[] buff)
+ {
+ if (UnpackCrunch(image_data, out var result))
+ {
+ if (DecodeETC2A8(result, buff))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private bool UnpackCrunch(byte[] image_data, out byte[] result)
{
- byte[] result;
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 3) //2017.3 and up
|| m_TextureFormat == TextureFormat.ETC_RGB4Crunched
|| m_TextureFormat == TextureFormat.ETC2_RGBA8Crunched)
@@ -694,8 +631,6 @@ namespace AssetStudio
}
if (result != null)
{
- image_data = result;
- image_data_size = result.Length;
return true;
}
return false;
diff --git a/AssetStudioUtility/Texture2DExtensions.cs b/AssetStudioUtility/Texture2DExtensions.cs
index bc24c78..0eafdf8 100644
--- a/AssetStudioUtility/Texture2DExtensions.cs
+++ b/AssetStudioUtility/Texture2DExtensions.cs
@@ -10,20 +10,27 @@ namespace AssetStudio
public static Bitmap ConvertToBitmap(this Texture2D m_Texture2D, bool flip)
{
var converter = new Texture2DConverter(m_Texture2D);
- var bytes = converter.DecodeTexture2D();
- if (bytes != null && bytes.Length > 0)
+ var bytes = BigArrayPool.Shared.Rent(m_Texture2D.m_Width * m_Texture2D.m_Height * 4);
+ try
{
- var bitmap = new Bitmap(m_Texture2D.m_Width, m_Texture2D.m_Height, PixelFormat.Format32bppArgb);
- var bmpData = bitmap.LockBits(new Rectangle(0, 0, m_Texture2D.m_Width, m_Texture2D.m_Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
- Marshal.Copy(bytes, 0, bmpData.Scan0, bytes.Length);
- bitmap.UnlockBits(bmpData);
- if (flip)
+ if (converter.DecodeTexture2D(bytes))
{
- bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
+ var bitmap = new Bitmap(m_Texture2D.m_Width, m_Texture2D.m_Height, PixelFormat.Format32bppArgb);
+ var bmpData = bitmap.LockBits(new Rectangle(0, 0, m_Texture2D.m_Width, m_Texture2D.m_Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
+ Marshal.Copy(bytes, 0, bmpData.Scan0, bitmap.Width * bitmap.Height * 4);
+ bitmap.UnlockBits(bmpData);
+ if (flip)
+ {
+ bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
+ }
+ return bitmap;
}
- return bitmap;
+ return null;
+ }
+ finally
+ {
+ BigArrayPool.Shared.Return(bytes);
}
- return null;
}
public static MemoryStream ConvertToStream(this Texture2D m_Texture2D, ImageFormat imageFormat, bool flip)