using AssetRipper.TextureDecoder.Astc; using AssetRipper.TextureDecoder.Rgb.Formats; namespace AssetRipper.TextureDecoder.Tests; public sealed class AstcTests { private const double MaxMeanDeviation4x4 = 0.2; private const double MaxStandardDeviation4x4 = 1; private const double MaxMeanDeviation5x5 = 0.2; private const double MaxStandardDeviation5x5 = 1; private const double MaxMeanDeviation6x6 = 0.2; private const double MaxStandardDeviation6x6 = 1; private const double MaxMeanDeviation8x8 = 0.2; private const double MaxStandardDeviation8x8 = 2; private const double MaxMeanDeviation10x10 = 0.2; private const double MaxStandardDeviation10x10 = 2.5; private const double MaxMeanDeviation12x12 = 0.3; private const double MaxStandardDeviation12x12 = 3; [Test] public void DecompressAstc4x4() => AssertCorrectDecompression(4, 4, MaxMeanDeviation4x4, MaxStandardDeviation4x4); [Test] public void DecompressAstc5x5() => AssertCorrectDecompression(5, 5, MaxMeanDeviation5x5, MaxStandardDeviation5x5); [Test] public void DecompressAstc6x6() => AssertCorrectDecompression(6, 6, MaxMeanDeviation6x6, MaxStandardDeviation6x6); [Test] public void DecompressAstc8x8() => AssertCorrectDecompression(8, 8, MaxMeanDeviation8x8, MaxStandardDeviation8x8); [Test] public void DecompressAstc10x10() => AssertCorrectDecompression(10, 10, MaxMeanDeviation10x10, MaxStandardDeviation10x10); [Test] public void DecompressAstc12x12() => AssertCorrectDecompression(12, 12, MaxMeanDeviation12x12, MaxStandardDeviation12x12); [Test] [Ignore("High dynamic range textures are not supported yet.")] public void DecompressAstc4x4HDR() => AssertCorrectDecompression(4, 4, MaxMeanDeviation4x4, MaxStandardDeviation4x4); [Test] [Ignore("High dynamic range textures are not supported yet.")] public void DecompressAstc5x5HDR() => AssertCorrectDecompression(5, 5, MaxMeanDeviation5x5, MaxStandardDeviation5x5); [Test] [Ignore("High dynamic range textures are not supported yet.")] public void DecompressAstc6x6HDR() => AssertCorrectDecompression(6, 6, MaxMeanDeviation6x6, MaxStandardDeviation6x6); [Test] [Ignore("High dynamic range textures are not supported yet.")] public void DecompressAstc8x8HDR() => AssertCorrectDecompression(8, 8, MaxMeanDeviation8x8, MaxStandardDeviation8x8); [Test] [Ignore("High dynamic range textures are not supported yet.")] public void DecompressAstc10x10HDR() => AssertCorrectDecompression(10, 10, MaxMeanDeviation10x10, MaxStandardDeviation10x10); [Test] [Ignore("High dynamic range textures are not supported yet.")] public void DecompressAstc12x12HDR() => AssertCorrectDecompression(4, 4, MaxMeanDeviation12x12, MaxStandardDeviation12x12); private static void AssertCorrectDecompression(int blockWidth, int blockHeight, double maxMeanDeviation, double maxStandardDeviation) where T : ITexture { ReadOnlySpan data = T.Data; int bytesRead = AstcDecoder.DecodeASTC, byte>(data, T.Width, T.Height, blockWidth, blockHeight, out byte[] decompressedData); if (!T.Mips) { Assert.That(bytesRead, Is.EqualTo(data.Length)); } ByteArrayDeviation.AssertMinimalDeviation(decompressedData, AndroidTextures.Logo_00.Data, maxMeanDeviation, maxStandardDeviation); } [TestCase(new byte[16] { 83, 1, 147, 104, 198, 173, 55, 116, 182, 66, 105, 11, 102, 43, 148, 125 }, 8, 8, TestName = "GetBits Should not throw in DecodeIntseq")] [TestCase(new byte[16] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 8, 8, TestName = "Zero blocks should not throw", Description = "Blocks of all zeros are valid")] [TestCase(new byte[16] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, 8, 8, TestName = "0xFF blocks should not throw", Description = "Blocks with all bits set are invalid, but should be handled gracefully")] public void DecodesBlockWithoutThrowing(byte[] block, int blockWidth, int blockHeight) { Assert.DoesNotThrow(() => AstcDecoder.DecodeASTC, byte>(block, blockWidth, blockHeight, blockWidth, blockHeight, out _)); } }