mirror of
https://github.com/AssetRipper/AssetRipper.TextureDecoder.git
synced 2026-11-13 02:21:29 -10:00
Ported Bc code
This commit is contained in:
1 parent
8458eb5866
commit
be63ebdb23
17 files changed
+2896
-1
No files matched your search
@@ -5,6 +5,8 @@
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<PublishSingleFile>true</PublishSingleFile>
|
||||
<PublishTrimmed>true</PublishTrimmed>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using AssetRipper.TextureDecoder.Astc;
|
||||
using AssetRipper.TextureDecoder.Atc;
|
||||
using AssetRipper.TextureDecoder.Bc;
|
||||
using AssetRipper.TextureDecoder.Dxt;
|
||||
using AssetRipper.TextureDecoder.Etc;
|
||||
using AssetRipper.TextureDecoder.Pvrtc;
|
||||
@@ -35,6 +36,9 @@ internal static class Program
|
||||
case "atc":
|
||||
DecodeAtc(data, width, height, args4, bitmap.Bits);
|
||||
break;
|
||||
case "bc":
|
||||
DecodeBc(data, width, height, args4, args5, bitmap.Bits);
|
||||
break;
|
||||
case "dxt":
|
||||
DecodeDxt(data, width, height, args4, bitmap.Bits);
|
||||
break;
|
||||
@@ -104,6 +108,47 @@ internal static class Program
|
||||
}
|
||||
}
|
||||
|
||||
private static void DecodeBc(ReadOnlySpan<byte> input, int width, int height, string modeString, string isSignedString, Span<byte> output)
|
||||
{
|
||||
Console.WriteLine("Arg at index 4 : mode");
|
||||
Console.WriteLine(" 1 - BC1");
|
||||
Console.WriteLine(" 2 - BC2");
|
||||
Console.WriteLine(" 3 - BC3");
|
||||
Console.WriteLine(" 4 - BC4");
|
||||
Console.WriteLine(" 5 - BC5");
|
||||
Console.WriteLine(" 6 - BC6H");
|
||||
Console.WriteLine(" 7 - BC7");
|
||||
Console.WriteLine("Arg at index 5 : isSigned (BC6H only)");
|
||||
int mode = int.Parse(modeString);
|
||||
switch (mode)
|
||||
{
|
||||
case 1:
|
||||
BcDecoder.DecompressBC1(input, width, height, output);
|
||||
break;
|
||||
case 2:
|
||||
BcDecoder.DecompressBC2(input, width, height, output);
|
||||
break;
|
||||
case 3:
|
||||
BcDecoder.DecompressBC3(input, width, height, output);
|
||||
break;
|
||||
case 4:
|
||||
BcDecoder.DecompressBC4(input, width, height, output);
|
||||
break;
|
||||
case 5:
|
||||
BcDecoder.DecompressBC5(input, width, height, output);
|
||||
break;
|
||||
case 6:
|
||||
BcDecoder.DecompressBC6H(input, width, height, bool.Parse(isSignedString), output);
|
||||
break;
|
||||
case 7:
|
||||
BcDecoder.DecompressBC7(input, width, height, output);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new NotSupportedException(mode.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private static void DecodeDxt(ReadOnlySpan<byte> input, int width, int height, string modeString, Span<byte> output)
|
||||
{
|
||||
Console.WriteLine("Arg at index 4 : mode");
|
||||
|
||||
@@ -0,0 +1,189 @@
|
||||
using AssetRipper.TextureDecoder.Bc;
|
||||
using AssetRipper.TextureDecoder.Dxt;
|
||||
|
||||
namespace AssetRipper.TextureDecoder.Tests
|
||||
{
|
||||
public sealed class BcTests
|
||||
{
|
||||
private const double MaxMeanDeviationBc6h = 0.5;
|
||||
private const double MaxMeanDeviationBc7 = 0.1;//Bc7 is more accurate than Bc6h
|
||||
private const double MaxStandardDeviationBc6h = 0.8;
|
||||
private const double MaxStandardDeviationBc7 = 0.8;
|
||||
|
||||
private static byte[] originalBgra32LogoData = Array.Empty<byte>();
|
||||
|
||||
[SetUp]
|
||||
public void InitializeOriginalData()
|
||||
{
|
||||
originalBgra32LogoData = File.ReadAllBytes(PathConstants.BcTestFilesFolder + "test.bgra32");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DecompressDXT1Test()
|
||||
{
|
||||
ReadOnlySpan<byte> data = File.ReadAllBytes(PathConstants.DxtTestFilesFolder + "test.dxt1");
|
||||
int totalBytesRead = 0;
|
||||
foreach (int size in new int[] { 256, 128, 64, 32, 16, 8, 4 }) //mipmaps 2 and 1 cause a buffer overrun for the output
|
||||
{
|
||||
int bytesRead = BcDecoder.DecompressBC1(data.Slice(totalBytesRead), size, size, out byte[] bcDecodedData);
|
||||
DxtDecoder.DecompressDXT1(data.Slice(totalBytesRead), size, size, out byte[] dxtDecodedData);
|
||||
totalBytesRead += bytesRead;
|
||||
AssertAlmostEqual(dxtDecodedData, bcDecodedData);
|
||||
}
|
||||
Assert.That(totalBytesRead + 16, Is.EqualTo(data.Length));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DecompressDXT3Test()
|
||||
{
|
||||
ReadOnlySpan<byte> data = File.ReadAllBytes(PathConstants.DxtTestFilesFolder + "test.dxt3");
|
||||
int totalBytesRead = 0;
|
||||
foreach (int size in new int[] { 256, 128, 64, 32, 16, 8, 4 }) //mipmaps 2 and 1 cause a buffer overrun for the output
|
||||
{
|
||||
int bytesRead = BcDecoder.DecompressBC2(data.Slice(totalBytesRead), size, size, out byte[] bcDecodedData);
|
||||
DxtDecoder.DecompressDXT3(data.Slice(totalBytesRead), size, size, out byte[] dxtDecodedData);
|
||||
totalBytesRead += bytesRead;
|
||||
AssertAlmostEqual(dxtDecodedData, bcDecodedData);
|
||||
}
|
||||
Assert.That(totalBytesRead + 32, Is.EqualTo(data.Length));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DecompressDXT5Test()
|
||||
{
|
||||
ReadOnlySpan<byte> data = File.ReadAllBytes(PathConstants.DxtTestFilesFolder + "test.dxt5");
|
||||
int totalBytesRead = 0;
|
||||
foreach (int size in new int[] { 256, 128, 64, 32, 16, 8, 4 }) //mipmaps 2 and 1 cause a buffer overrun for the output
|
||||
{
|
||||
int bytesRead = BcDecoder.DecompressBC3(data.Slice(totalBytesRead), size, size, out byte[] bcDecodedData);
|
||||
DxtDecoder.DecompressDXT5(data.Slice(totalBytesRead), size, size, out byte[] dxtDecodedData);
|
||||
totalBytesRead += bytesRead;
|
||||
AssertAlmostEqual(dxtDecodedData, bcDecodedData);
|
||||
}
|
||||
Assert.That(totalBytesRead + 32, Is.EqualTo(data.Length));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DecompressBC4Test()
|
||||
{
|
||||
ReadOnlySpan<byte> data = File.ReadAllBytes(PathConstants.BcTestFilesFolder + "test.bc4");
|
||||
int bytesRead = BcDecoder.DecompressBC4(data, 512, 512, out _);
|
||||
Assert.That(bytesRead, Is.EqualTo(data.Length));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DecompressBC5Test()
|
||||
{
|
||||
ReadOnlySpan<byte> data = File.ReadAllBytes(PathConstants.BcTestFilesFolder + "test.bc5");
|
||||
int bytesRead = BcDecoder.DecompressBC5(data, 512, 512, out _);
|
||||
Assert.That(bytesRead, Is.EqualTo(data.Length));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DecompressBC6HFastTest()
|
||||
{
|
||||
AssertCorrectBC6HDecompression(PathConstants.BcTestFilesFolder + "test.bc6h_fast", 512, 512, false);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DecompressBC6HNormalTest()
|
||||
{
|
||||
AssertCorrectBC6HDecompression(PathConstants.BcTestFilesFolder + "test.bc6h_normal", 512, 512, false);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DecompressBC6HBestTest()
|
||||
{
|
||||
AssertCorrectBC6HDecompression(PathConstants.BcTestFilesFolder + "test.bc6h_best", 512, 512, false);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DecompressBC7FastTest()
|
||||
{
|
||||
AssertCorrectBC7Decompression(PathConstants.BcTestFilesFolder + "test.bc7_fast", 512, 512);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DecompressBC7NormalTest()
|
||||
{
|
||||
AssertCorrectBC7Decompression(PathConstants.BcTestFilesFolder + "test.bc7_normal", 512, 512);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DecompressBC7BestTest()
|
||||
{
|
||||
AssertCorrectBC7Decompression(PathConstants.BcTestFilesFolder + "test.bc7_best", 512, 512);
|
||||
}
|
||||
|
||||
private static void AssertCorrectBC6HDecompression(string path, int width, int height, bool isSigned)
|
||||
{
|
||||
ReadOnlySpan<byte> data = File.ReadAllBytes(path);
|
||||
int bytesRead = BcDecoder.DecompressBC6H(data, width, height, isSigned, out byte[] decodedData);
|
||||
Assert.That(bytesRead, Is.EqualTo(data.Length));
|
||||
AssertMinimalDeviation(decodedData, originalBgra32LogoData, MaxMeanDeviationBc6h, MaxStandardDeviationBc6h);
|
||||
}
|
||||
|
||||
private static void AssertCorrectBC7Decompression(string path, int width, int height)
|
||||
{
|
||||
ReadOnlySpan<byte> data = File.ReadAllBytes(path);
|
||||
int bytesRead = BcDecoder.DecompressBC7(data, width, height, out byte[] decodedData);
|
||||
Assert.That(bytesRead, Is.EqualTo(data.Length));
|
||||
AssertMinimalDeviation(decodedData, originalBgra32LogoData, MaxMeanDeviationBc7, MaxStandardDeviationBc7);
|
||||
}
|
||||
|
||||
private static void AssertAlmostEqual(byte[] array1, byte[] array2, int maxDifference = 2)
|
||||
{
|
||||
if (array1.Length != array2.Length)
|
||||
{
|
||||
Assert.Fail($"Differing array lengths\nArray 1 length {array1.Length}\nArray 2 length {array2.Length}");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < array1.Length; i++)
|
||||
{
|
||||
int difference = Math.Abs(array1[i] - array2[i]);
|
||||
if (difference > maxDifference)
|
||||
{
|
||||
Assert.Fail($"Differing values at index {i}\nArray 1: {array1[i]}\nArray 2: {array2[i]}");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void AssertMinimalDeviation(byte[] decoded, byte[] original, double maxMeanDeviation, double maxStandardDeviation)
|
||||
{
|
||||
if (decoded.Length != original.Length)
|
||||
{
|
||||
Assert.Fail($"Differing array lengths\nDecoded length {decoded.Length}\nOriginal length {original.Length}");
|
||||
return;
|
||||
}
|
||||
|
||||
long differenceSum = 0;
|
||||
|
||||
for (int i = 0; i < decoded.Length; i++)
|
||||
{
|
||||
differenceSum += decoded[i] - original[i];
|
||||
}
|
||||
|
||||
double mean = differenceSum / (double)decoded.Length;
|
||||
|
||||
double sumOfSquaredDeviations = 0;
|
||||
|
||||
for (int i = 0; i < decoded.Length; i++)
|
||||
{
|
||||
double deviation = decoded[i] - original[i] - mean;
|
||||
sumOfSquaredDeviations += deviation * deviation;
|
||||
}
|
||||
|
||||
double standardDeviation = Math.Sqrt(sumOfSquaredDeviations / (decoded.Length - 1));
|
||||
//Not sure if Bessel's correction is needed here, but it doesn't hurt, especially since length is around 1 million in the current use.
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(mean, Is.LessThan(maxMeanDeviation), "Mean too far positive");
|
||||
Assert.That(mean, Is.GreaterThan(-maxMeanDeviation), "Mean too far negative");
|
||||
Assert.That(standardDeviation, Is.LessThan(maxStandardDeviation), "Standard deviation too large");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,249 @@
|
||||
namespace AssetRipper.TextureDecoder.Bc;
|
||||
|
||||
internal static class Bc6hTables
|
||||
{
|
||||
internal static byte[][] ActualBitsCount =
|
||||
{
|
||||
new byte[] {10, 7, 11, 11, 11, 9, 8, 8, 8, 6, 10, 11, 12, 16},
|
||||
new byte[] {5, 6, 5, 4, 4, 5, 6, 5, 5, 6, 10, 9, 8, 4},
|
||||
new byte[] {5, 6, 4, 5, 4, 5, 5, 6, 5, 6, 10, 9, 8, 4},
|
||||
new byte[] {5, 6, 4, 4, 5, 5, 5, 5, 6, 6, 10, 9, 8, 4}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// There are 32 possible partition sets for a two-region tile.
|
||||
/// Each 4x4 block represents a single shape.
|
||||
/// Here also every fix-up index has MSB bit set.
|
||||
/// </summary>
|
||||
internal static byte[][][] PartitionSets =
|
||||
{
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 1, 1},
|
||||
new byte[] {0, 0, 1, 1},
|
||||
new byte[] {0, 0, 1, 1},
|
||||
new byte[] {0, 0, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 1},
|
||||
new byte[] {0, 0, 0, 1},
|
||||
new byte[] {0, 0, 0, 1},
|
||||
new byte[] {0, 0, 0, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 1, 1},
|
||||
new byte[] {0, 1, 1, 1},
|
||||
new byte[] {0, 1, 1, 1},
|
||||
new byte[] {0, 1, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 1},
|
||||
new byte[] {0, 0, 1, 1},
|
||||
new byte[] {0, 0, 1, 1},
|
||||
new byte[] {0, 1, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {0, 0, 0, 1},
|
||||
new byte[] {0, 0, 0, 1},
|
||||
new byte[] {0, 0, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 1, 1},
|
||||
new byte[] {0, 1, 1, 1},
|
||||
new byte[] {0, 1, 1, 1},
|
||||
new byte[] {1, 1, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 1},
|
||||
new byte[] {0, 0, 1, 1},
|
||||
new byte[] {0, 1, 1, 1},
|
||||
new byte[] {1, 1, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {0, 0, 0, 1},
|
||||
new byte[] {0, 0, 1, 1},
|
||||
new byte[] {0, 1, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {0, 0, 0, 0},
|
||||
new byte[] {0, 0, 0, 1},
|
||||
new byte[] {0, 0, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 1, 1},
|
||||
new byte[] {0, 1, 1, 1},
|
||||
new byte[] {1, 1, 1, 1},
|
||||
new byte[] {1, 1, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {0, 0, 0, 1},
|
||||
new byte[] {0, 1, 1, 1},
|
||||
new byte[] {1, 1, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {0, 0, 0, 0},
|
||||
new byte[] {0, 0, 0, 1},
|
||||
new byte[] {0, 1, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 1},
|
||||
new byte[] {0, 1, 1, 1},
|
||||
new byte[] {1, 1, 1, 1},
|
||||
new byte[] {1, 1, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {0, 0, 0, 0},
|
||||
new byte[] {1, 1, 1, 1},
|
||||
new byte[] {1, 1, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {1, 1, 1, 1},
|
||||
new byte[] {1, 1, 1, 1},
|
||||
new byte[] {1, 1, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {0, 0, 0, 0},
|
||||
new byte[] {0, 0, 0, 0},
|
||||
new byte[] {1, 1, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {1, 0, 0, 0},
|
||||
new byte[] {1, 1, 1, 0},
|
||||
new byte[] {1, 1, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 129, 1},
|
||||
new byte[] {0, 0, 0, 1},
|
||||
new byte[] {0, 0, 0, 0},
|
||||
new byte[] {0, 0, 0, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {0, 0, 0, 0},
|
||||
new byte[] {129, 0, 0, 0},
|
||||
new byte[] {1, 1, 1, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 129, 1},
|
||||
new byte[] {0, 0, 1, 1},
|
||||
new byte[] {0, 0, 0, 1},
|
||||
new byte[] {0, 0, 0, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 129, 1},
|
||||
new byte[] {0, 0, 0, 1},
|
||||
new byte[] {0, 0, 0, 0},
|
||||
new byte[] {0, 0, 0, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {1, 0, 0, 0},
|
||||
new byte[] {129, 1, 0, 0},
|
||||
new byte[] {1, 1, 1, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {0, 0, 0, 0},
|
||||
new byte[] {129, 0, 0, 0},
|
||||
new byte[] {1, 1, 0, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 1, 1},
|
||||
new byte[] {0, 0, 1, 1},
|
||||
new byte[] {0, 0, 1, 1},
|
||||
new byte[] {0, 0, 0, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 129, 1},
|
||||
new byte[] {0, 0, 0, 1},
|
||||
new byte[] {0, 0, 0, 1},
|
||||
new byte[] {0, 0, 0, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {1, 0, 0, 0},
|
||||
new byte[] {129, 0, 0, 0},
|
||||
new byte[] {1, 1, 0, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 129, 0},
|
||||
new byte[] {0, 1, 1, 0},
|
||||
new byte[] {0, 1, 1, 0},
|
||||
new byte[] {0, 1, 1, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 129, 1},
|
||||
new byte[] {0, 1, 1, 0},
|
||||
new byte[] {0, 1, 1, 0},
|
||||
new byte[] {1, 1, 0, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 1},
|
||||
new byte[] {0, 1, 1, 1},
|
||||
new byte[] {129, 1, 1, 0},
|
||||
new byte[] {1, 0, 0, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {1, 1, 1, 1},
|
||||
new byte[] {129, 1, 1, 1},
|
||||
new byte[] {0, 0, 0, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 129, 1},
|
||||
new byte[] {0, 0, 0, 1},
|
||||
new byte[] {1, 0, 0, 0},
|
||||
new byte[] {1, 1, 1, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 129, 1},
|
||||
new byte[] {1, 0, 0, 1},
|
||||
new byte[] {1, 0, 0, 1},
|
||||
new byte[] {1, 1, 0, 0}
|
||||
}
|
||||
};
|
||||
|
||||
internal static int[] AWeight3 = { 0, 9, 18, 27, 37, 46, 55, 64 };
|
||||
|
||||
internal static int[] AWeight4 = { 0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64 };
|
||||
}
|
||||
@@ -0,0 +1,929 @@
|
||||
namespace AssetRipper.TextureDecoder.Bc;
|
||||
|
||||
internal static class Bc7Tables
|
||||
{
|
||||
internal static byte[][] bcdec_bc7_actual_bits_count =
|
||||
{
|
||||
new byte[] { 4, 6, 5, 7, 5, 7, 7, 5 },
|
||||
new byte[] { 0, 0, 0, 0, 6, 8, 7, 5 }
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// There are 64 possible partition sets for a two-region tile.
|
||||
/// Each 4x4 block represents a single shape.
|
||||
/// Here also every fix-up index has MSB bit set.
|
||||
/// </summary>
|
||||
internal static byte[][][][] bcdec_bc7_partition_sets =
|
||||
{
|
||||
new byte[][][]
|
||||
{
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 1, 1},
|
||||
new byte[] {0, 0, 1, 1},
|
||||
new byte[] {0, 0, 1, 1},
|
||||
new byte[] {0, 0, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 1},
|
||||
new byte[] {0, 0, 0, 1},
|
||||
new byte[] {0, 0, 0, 1},
|
||||
new byte[] {0, 0, 0, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 1, 1},
|
||||
new byte[] {0, 1, 1, 1},
|
||||
new byte[] {0, 1, 1, 1},
|
||||
new byte[] {0, 1, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 1},
|
||||
new byte[] {0, 0, 1, 1},
|
||||
new byte[] {0, 0, 1, 1},
|
||||
new byte[] {0, 1, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {0, 0, 0, 1},
|
||||
new byte[] {0, 0, 0, 1},
|
||||
new byte[] {0, 0, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 1, 1},
|
||||
new byte[] {0, 1, 1, 1},
|
||||
new byte[] {0, 1, 1, 1},
|
||||
new byte[] {1, 1, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 1},
|
||||
new byte[] {0, 0, 1, 1},
|
||||
new byte[] {0, 1, 1, 1},
|
||||
new byte[] {1, 1, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {0, 0, 0, 1},
|
||||
new byte[] {0, 0, 1, 1},
|
||||
new byte[] {0, 1, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {0, 0, 0, 0},
|
||||
new byte[] {0, 0, 0, 1},
|
||||
new byte[] {0, 0, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 1, 1},
|
||||
new byte[] {0, 1, 1, 1},
|
||||
new byte[] {1, 1, 1, 1},
|
||||
new byte[] {1, 1, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {0, 0, 0, 1},
|
||||
new byte[] {0, 1, 1, 1},
|
||||
new byte[] {1, 1, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {0, 0, 0, 0},
|
||||
new byte[] {0, 0, 0, 1},
|
||||
new byte[] {0, 1, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 1},
|
||||
new byte[] {0, 1, 1, 1},
|
||||
new byte[] {1, 1, 1, 1},
|
||||
new byte[] {1, 1, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {0, 0, 0, 0},
|
||||
new byte[] {1, 1, 1, 1},
|
||||
new byte[] {1, 1, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {1, 1, 1, 1},
|
||||
new byte[] {1, 1, 1, 1},
|
||||
new byte[] {1, 1, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {0, 0, 0, 0},
|
||||
new byte[] {0, 0, 0, 0},
|
||||
new byte[] {1, 1, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {1, 0, 0, 0},
|
||||
new byte[] {1, 1, 1, 0},
|
||||
new byte[] {1, 1, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 129, 1},
|
||||
new byte[] {0, 0, 0, 1},
|
||||
new byte[] {0, 0, 0, 0},
|
||||
new byte[] {0, 0, 0, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {0, 0, 0, 0},
|
||||
new byte[] {129, 0, 0, 0},
|
||||
new byte[] {1, 1, 1, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 129, 1},
|
||||
new byte[] {0, 0, 1, 1},
|
||||
new byte[] {0, 0, 0, 1},
|
||||
new byte[] {0, 0, 0, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 129, 1},
|
||||
new byte[] {0, 0, 0, 1},
|
||||
new byte[] {0, 0, 0, 0},
|
||||
new byte[] {0, 0, 0, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {1, 0, 0, 0},
|
||||
new byte[] {129, 1, 0, 0},
|
||||
new byte[] {1, 1, 1, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {0, 0, 0, 0},
|
||||
new byte[] {129, 0, 0, 0},
|
||||
new byte[] {1, 1, 0, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 1, 1},
|
||||
new byte[] {0, 0, 1, 1},
|
||||
new byte[] {0, 0, 1, 1},
|
||||
new byte[] {0, 0, 0, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 129, 1},
|
||||
new byte[] {0, 0, 0, 1},
|
||||
new byte[] {0, 0, 0, 1},
|
||||
new byte[] {0, 0, 0, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {1, 0, 0, 0},
|
||||
new byte[] {129, 0, 0, 0},
|
||||
new byte[] {1, 1, 0, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 129, 0},
|
||||
new byte[] {0, 1, 1, 0},
|
||||
new byte[] {0, 1, 1, 0},
|
||||
new byte[] {0, 1, 1, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 129, 1},
|
||||
new byte[] {0, 1, 1, 0},
|
||||
new byte[] {0, 1, 1, 0},
|
||||
new byte[] {1, 1, 0, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 1},
|
||||
new byte[] {0, 1, 1, 1},
|
||||
new byte[] {129, 1, 1, 0},
|
||||
new byte[] {1, 0, 0, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {1, 1, 1, 1},
|
||||
new byte[] {129, 1, 1, 1},
|
||||
new byte[] {0, 0, 0, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 129, 1},
|
||||
new byte[] {0, 0, 0, 1},
|
||||
new byte[] {1, 0, 0, 0},
|
||||
new byte[] {1, 1, 1, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 129, 1},
|
||||
new byte[] {1, 0, 0, 1},
|
||||
new byte[] {1, 0, 0, 1},
|
||||
new byte[] {1, 1, 0, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 0, 1},
|
||||
new byte[] {0, 1, 0, 1},
|
||||
new byte[] {0, 1, 0, 1},
|
||||
new byte[] {0, 1, 0, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {1, 1, 1, 1},
|
||||
new byte[] {0, 0, 0, 0},
|
||||
new byte[] {1, 1, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 0, 1},
|
||||
new byte[] {1, 0, 129, 0},
|
||||
new byte[] {0, 1, 0, 1},
|
||||
new byte[] {1, 0, 1, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 1, 1},
|
||||
new byte[] {0, 0, 1, 1},
|
||||
new byte[] {129, 1, 0, 0},
|
||||
new byte[] {1, 1, 0, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 129, 1},
|
||||
new byte[] {1, 1, 0, 0},
|
||||
new byte[] {0, 0, 1, 1},
|
||||
new byte[] {1, 1, 0, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 0, 1},
|
||||
new byte[] {0, 1, 0, 1},
|
||||
new byte[] {129, 0, 1, 0},
|
||||
new byte[] {1, 0, 1, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 1, 0},
|
||||
new byte[] {1, 0, 0, 1},
|
||||
new byte[] {0, 1, 1, 0},
|
||||
new byte[] {1, 0, 0, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 0, 1},
|
||||
new byte[] {1, 0, 1, 0},
|
||||
new byte[] {1, 0, 1, 0},
|
||||
new byte[] {0, 1, 0, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 129, 1},
|
||||
new byte[] {0, 0, 1, 1},
|
||||
new byte[] {1, 1, 0, 0},
|
||||
new byte[] {1, 1, 1, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 1},
|
||||
new byte[] {0, 0, 1, 1},
|
||||
new byte[] {129, 1, 0, 0},
|
||||
new byte[] {1, 0, 0, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 129, 1},
|
||||
new byte[] {0, 0, 1, 0},
|
||||
new byte[] {0, 1, 0, 0},
|
||||
new byte[] {1, 1, 0, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 129, 1},
|
||||
new byte[] {1, 0, 1, 1},
|
||||
new byte[] {1, 1, 0, 1},
|
||||
new byte[] {1, 1, 0, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 129, 0},
|
||||
new byte[] {1, 0, 0, 1},
|
||||
new byte[] {1, 0, 0, 1},
|
||||
new byte[] {0, 1, 1, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 1, 1},
|
||||
new byte[] {1, 1, 0, 0},
|
||||
new byte[] {1, 1, 0, 0},
|
||||
new byte[] {0, 0, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 1, 0},
|
||||
new byte[] {0, 1, 1, 0},
|
||||
new byte[] {1, 0, 0, 1},
|
||||
new byte[] {1, 0, 0, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {0, 1, 129, 0},
|
||||
new byte[] {0, 1, 1, 0},
|
||||
new byte[] {0, 0, 0, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 0, 0},
|
||||
new byte[] {1, 1, 129, 0},
|
||||
new byte[] {0, 1, 0, 0},
|
||||
new byte[] {0, 0, 0, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 129, 0},
|
||||
new byte[] {0, 1, 1, 1},
|
||||
new byte[] {0, 0, 1, 0},
|
||||
new byte[] {0, 0, 0, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {0, 0, 129, 0},
|
||||
new byte[] {0, 1, 1, 1},
|
||||
new byte[] {0, 0, 1, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {0, 1, 0, 0},
|
||||
new byte[] {129, 1, 1, 0},
|
||||
new byte[] {0, 1, 0, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 1, 0},
|
||||
new byte[] {1, 1, 0, 0},
|
||||
new byte[] {1, 0, 0, 1},
|
||||
new byte[] {0, 0, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 1, 1},
|
||||
new byte[] {0, 1, 1, 0},
|
||||
new byte[] {1, 1, 0, 0},
|
||||
new byte[] {1, 0, 0, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 129, 0},
|
||||
new byte[] {0, 0, 1, 1},
|
||||
new byte[] {1, 0, 0, 1},
|
||||
new byte[] {1, 1, 0, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 129, 1},
|
||||
new byte[] {1, 0, 0, 1},
|
||||
new byte[] {1, 1, 0, 0},
|
||||
new byte[] {0, 1, 1, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 1, 0},
|
||||
new byte[] {1, 1, 0, 0},
|
||||
new byte[] {1, 1, 0, 0},
|
||||
new byte[] {1, 0, 0, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 1, 0},
|
||||
new byte[] {0, 0, 1, 1},
|
||||
new byte[] {0, 0, 1, 1},
|
||||
new byte[] {1, 0, 0, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 1, 1},
|
||||
new byte[] {1, 1, 1, 0},
|
||||
new byte[] {1, 0, 0, 0},
|
||||
new byte[] {0, 0, 0, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 1},
|
||||
new byte[] {1, 0, 0, 0},
|
||||
new byte[] {1, 1, 1, 0},
|
||||
new byte[] {0, 1, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {1, 1, 1, 1},
|
||||
new byte[] {0, 0, 1, 1},
|
||||
new byte[] {0, 0, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 129, 1},
|
||||
new byte[] {0, 0, 1, 1},
|
||||
new byte[] {1, 1, 1, 1},
|
||||
new byte[] {0, 0, 0, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 129, 0},
|
||||
new byte[] {0, 0, 1, 0},
|
||||
new byte[] {1, 1, 1, 0},
|
||||
new byte[] {1, 1, 1, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 0, 0},
|
||||
new byte[] {0, 1, 0, 0},
|
||||
new byte[] {0, 1, 1, 1},
|
||||
new byte[] {0, 1, 1, 129}
|
||||
}
|
||||
},
|
||||
new byte[][][]
|
||||
{
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 1, 129},
|
||||
new byte[] {0, 0, 1, 1},
|
||||
new byte[] {0, 2, 2, 1},
|
||||
new byte[] {2, 2, 2, 130}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 129},
|
||||
new byte[] {0, 0, 1, 1},
|
||||
new byte[] {130, 2, 1, 1},
|
||||
new byte[] {2, 2, 2, 1}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {2, 0, 0, 1},
|
||||
new byte[] {130, 2, 1, 1},
|
||||
new byte[] {2, 2, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 2, 2, 130},
|
||||
new byte[] {0, 0, 2, 2},
|
||||
new byte[] {0, 0, 1, 1},
|
||||
new byte[] {0, 1, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {0, 0, 0, 0},
|
||||
new byte[] {129, 1, 2, 2},
|
||||
new byte[] {1, 1, 2, 130}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 1, 129},
|
||||
new byte[] {0, 0, 1, 1},
|
||||
new byte[] {0, 0, 2, 2},
|
||||
new byte[] {0, 0, 2, 130}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 2, 130},
|
||||
new byte[] {0, 0, 2, 2},
|
||||
new byte[] {1, 1, 1, 1},
|
||||
new byte[] {1, 1, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 1, 1},
|
||||
new byte[] {0, 0, 1, 1},
|
||||
new byte[] {130, 2, 1, 1},
|
||||
new byte[] {2, 2, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {0, 0, 0, 0},
|
||||
new byte[] {129, 1, 1, 1},
|
||||
new byte[] {2, 2, 2, 130}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {1, 1, 1, 1},
|
||||
new byte[] {129, 1, 1, 1},
|
||||
new byte[] {2, 2, 2, 130}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {1, 1, 129, 1},
|
||||
new byte[] {2, 2, 2, 2},
|
||||
new byte[] {2, 2, 2, 130}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 1, 2},
|
||||
new byte[] {0, 0, 129, 2},
|
||||
new byte[] {0, 0, 1, 2},
|
||||
new byte[] {0, 0, 1, 130}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 1, 2},
|
||||
new byte[] {0, 1, 129, 2},
|
||||
new byte[] {0, 1, 1, 2},
|
||||
new byte[] {0, 1, 1, 130}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 2, 2},
|
||||
new byte[] {0, 129, 2, 2},
|
||||
new byte[] {0, 1, 2, 2},
|
||||
new byte[] {0, 1, 2, 130}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 1, 129},
|
||||
new byte[] {0, 1, 1, 2},
|
||||
new byte[] {1, 1, 2, 2},
|
||||
new byte[] {1, 2, 2, 130}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 1, 129},
|
||||
new byte[] {2, 0, 0, 1},
|
||||
new byte[] {130, 2, 0, 0},
|
||||
new byte[] {2, 2, 2, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 129},
|
||||
new byte[] {0, 0, 1, 1},
|
||||
new byte[] {0, 1, 1, 2},
|
||||
new byte[] {1, 1, 2, 130}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 1, 129},
|
||||
new byte[] {0, 0, 1, 1},
|
||||
new byte[] {130, 0, 0, 1},
|
||||
new byte[] {2, 2, 0, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {1, 1, 2, 2},
|
||||
new byte[] {129, 1, 2, 2},
|
||||
new byte[] {1, 1, 2, 130}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 2, 130},
|
||||
new byte[] {0, 0, 2, 2},
|
||||
new byte[] {0, 0, 2, 2},
|
||||
new byte[] {1, 1, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 1, 129},
|
||||
new byte[] {0, 1, 1, 1},
|
||||
new byte[] {0, 2, 2, 2},
|
||||
new byte[] {0, 2, 2, 130}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 129},
|
||||
new byte[] {0, 0, 0, 1},
|
||||
new byte[] {130, 2, 2, 1},
|
||||
new byte[] {2, 2, 2, 1}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {0, 0, 129, 1},
|
||||
new byte[] {0, 1, 2, 2},
|
||||
new byte[] {0, 1, 2, 130}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {1, 1, 0, 0},
|
||||
new byte[] {130, 2, 129, 0},
|
||||
new byte[] {2, 2, 1, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 2, 130},
|
||||
new byte[] {0, 129, 2, 2},
|
||||
new byte[] {0, 0, 1, 1},
|
||||
new byte[] {0, 0, 0, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 1, 2},
|
||||
new byte[] {0, 0, 1, 2},
|
||||
new byte[] {129, 1, 2, 2},
|
||||
new byte[] {2, 2, 2, 130}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 1, 0},
|
||||
new byte[] {1, 2, 130, 1},
|
||||
new byte[] {129, 2, 2, 1},
|
||||
new byte[] {0, 1, 1, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {0, 1, 129, 0},
|
||||
new byte[] {1, 2, 130, 1},
|
||||
new byte[] {1, 2, 2, 1}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 2, 2},
|
||||
new byte[] {1, 1, 0, 2},
|
||||
new byte[] {129, 1, 0, 2},
|
||||
new byte[] {0, 0, 2, 130}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 1, 0},
|
||||
new byte[] {0, 129, 1, 0},
|
||||
new byte[] {2, 0, 0, 2},
|
||||
new byte[] {2, 2, 2, 130}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 1, 1},
|
||||
new byte[] {0, 1, 2, 2},
|
||||
new byte[] {0, 1, 130, 2},
|
||||
new byte[] {0, 0, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {2, 0, 0, 0},
|
||||
new byte[] {130, 2, 1, 1},
|
||||
new byte[] {2, 2, 2, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {0, 0, 0, 2},
|
||||
new byte[] {129, 1, 2, 2},
|
||||
new byte[] {1, 2, 2, 130}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 2, 2, 130},
|
||||
new byte[] {0, 0, 2, 2},
|
||||
new byte[] {0, 0, 1, 2},
|
||||
new byte[] {0, 0, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 1, 129},
|
||||
new byte[] {0, 0, 1, 2},
|
||||
new byte[] {0, 0, 2, 2},
|
||||
new byte[] {0, 2, 2, 130}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 2, 0},
|
||||
new byte[] {0, 129, 2, 0},
|
||||
new byte[] {0, 1, 130, 0},
|
||||
new byte[] {0, 1, 2, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {1, 1, 129, 1},
|
||||
new byte[] {2, 2, 130, 2},
|
||||
new byte[] {0, 0, 0, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 2, 0},
|
||||
new byte[] {1, 2, 0, 1},
|
||||
new byte[] {130, 0, 129, 2},
|
||||
new byte[] {0, 1, 2, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 2, 0},
|
||||
new byte[] {2, 0, 1, 2},
|
||||
new byte[] {129, 130, 0, 1},
|
||||
new byte[] {0, 1, 2, 0}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 1, 1},
|
||||
new byte[] {2, 2, 0, 0},
|
||||
new byte[] {1, 1, 130, 2},
|
||||
new byte[] {0, 0, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 1, 1},
|
||||
new byte[] {1, 1, 130, 2},
|
||||
new byte[] {2, 2, 0, 0},
|
||||
new byte[] {0, 0, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 0, 129},
|
||||
new byte[] {0, 1, 0, 1},
|
||||
new byte[] {2, 2, 2, 2},
|
||||
new byte[] {2, 2, 2, 130}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {0, 0, 0, 0},
|
||||
new byte[] {130, 1, 2, 1},
|
||||
new byte[] {2, 1, 2, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 2, 2},
|
||||
new byte[] {1, 129, 2, 2},
|
||||
new byte[] {0, 0, 2, 2},
|
||||
new byte[] {1, 1, 2, 130}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 2, 130},
|
||||
new byte[] {0, 0, 1, 1},
|
||||
new byte[] {0, 0, 2, 2},
|
||||
new byte[] {0, 0, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 2, 2, 0},
|
||||
new byte[] {1, 2, 130, 1},
|
||||
new byte[] {0, 2, 2, 0},
|
||||
new byte[] {1, 2, 2, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 0, 1},
|
||||
new byte[] {2, 2, 130, 2},
|
||||
new byte[] {2, 2, 2, 2},
|
||||
new byte[] {0, 1, 0, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {2, 1, 2, 1},
|
||||
new byte[] {130, 1, 2, 1},
|
||||
new byte[] {2, 1, 2, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 0, 129},
|
||||
new byte[] {0, 1, 0, 1},
|
||||
new byte[] {0, 1, 0, 1},
|
||||
new byte[] {2, 2, 2, 130}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 2, 2, 130},
|
||||
new byte[] {0, 1, 1, 1},
|
||||
new byte[] {0, 2, 2, 2},
|
||||
new byte[] {0, 1, 1, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 2},
|
||||
new byte[] {1, 129, 1, 2},
|
||||
new byte[] {0, 0, 0, 2},
|
||||
new byte[] {1, 1, 1, 130}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {2, 129, 1, 2},
|
||||
new byte[] {2, 1, 1, 2},
|
||||
new byte[] {2, 1, 1, 130}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 2, 2, 2},
|
||||
new byte[] {0, 129, 1, 1},
|
||||
new byte[] {0, 1, 1, 1},
|
||||
new byte[] {0, 2, 2, 130}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 2},
|
||||
new byte[] {1, 1, 1, 2},
|
||||
new byte[] {129, 1, 1, 2},
|
||||
new byte[] {0, 0, 0, 130}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 1, 0},
|
||||
new byte[] {0, 129, 1, 0},
|
||||
new byte[] {0, 1, 1, 0},
|
||||
new byte[] {2, 2, 2, 130}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {0, 0, 0, 0},
|
||||
new byte[] {2, 1, 129, 2},
|
||||
new byte[] {2, 1, 1, 130}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 1, 0},
|
||||
new byte[] {0, 129, 1, 0},
|
||||
new byte[] {2, 2, 2, 2},
|
||||
new byte[] {2, 2, 2, 130}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 2, 2},
|
||||
new byte[] {0, 0, 1, 1},
|
||||
new byte[] {0, 0, 129, 1},
|
||||
new byte[] {0, 0, 2, 130}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 2, 2},
|
||||
new byte[] {1, 1, 2, 2},
|
||||
new byte[] {129, 1, 2, 2},
|
||||
new byte[] {0, 0, 2, 130}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 0},
|
||||
new byte[] {0, 0, 0, 0},
|
||||
new byte[] {0, 0, 0, 0},
|
||||
new byte[] {2, 129, 1, 130}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 0, 0, 130},
|
||||
new byte[] {0, 0, 0, 1},
|
||||
new byte[] {0, 0, 0, 2},
|
||||
new byte[] {0, 0, 0, 129}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 2, 2, 2},
|
||||
new byte[] {1, 2, 2, 2},
|
||||
new byte[] {0, 2, 2, 2},
|
||||
new byte[] {129, 2, 2, 130}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 0, 129},
|
||||
new byte[] {2, 2, 2, 2},
|
||||
new byte[] {2, 2, 2, 2},
|
||||
new byte[] {2, 2, 2, 130}
|
||||
},
|
||||
new byte[][]
|
||||
{
|
||||
new byte[] {128, 1, 1, 129},
|
||||
new byte[] {2, 0, 1, 1},
|
||||
new byte[] {130, 2, 0, 1},
|
||||
new byte[] {2, 2, 2, 0}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
internal static int[] AWeight2 = { 0, 21, 43, 64 };
|
||||
|
||||
internal static int[] AWeight3 = { 0, 9, 18, 27, 37, 46, 55, 64 };
|
||||
|
||||
internal static int[] AWeight4 = { 0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64 };
|
||||
|
||||
internal const byte bcdec_bc7_sModeHasPBits = 0b11001011;
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
using AssetRipper.TextureDecoder.Rgb;
|
||||
using AssetRipper.TextureDecoder.Rgb.Formats;
|
||||
|
||||
namespace AssetRipper.TextureDecoder.Bc
|
||||
{
|
||||
public static class BcDecoder
|
||||
{
|
||||
public static int DecompressBC1(ReadOnlySpan<byte> input, int width, int height, out byte[] output)
|
||||
{
|
||||
output = new byte[width * height * Unsafe.SizeOf<ColorBGRA32>()];
|
||||
return DecompressBC1(input, width, height, output);
|
||||
}
|
||||
|
||||
public static int DecompressBC1(ReadOnlySpan<byte> input, int width, int height, Span<byte> output)
|
||||
{
|
||||
int inputOffset = 0;
|
||||
for (int i = 0; i < height; i += 4)
|
||||
{
|
||||
for (int j = 0; j < width; j += 4)
|
||||
{
|
||||
int outputOffset = ((i * width) + j) * Unsafe.SizeOf<ColorRGBA32>();
|
||||
BcHelpers.DecompressBc1(input.Slice(inputOffset, DefineConstants.BCDEC_BC1_BLOCK_SIZE), output.Slice(outputOffset), width * 4);
|
||||
inputOffset += DefineConstants.BCDEC_BC1_BLOCK_SIZE;
|
||||
}
|
||||
}
|
||||
RgbConverter.Convert<ColorRGBA32, byte, ColorBGRA32, byte>(output, width, height, output);
|
||||
return inputOffset;
|
||||
}
|
||||
|
||||
public static int DecompressBC2(ReadOnlySpan<byte> input, int width, int height, out byte[] output)
|
||||
{
|
||||
output = new byte[width * height * Unsafe.SizeOf<ColorBGRA32>()];
|
||||
return DecompressBC2(input, width, height, output);
|
||||
}
|
||||
|
||||
public static int DecompressBC2(ReadOnlySpan<byte> input, int width, int height, Span<byte> output)
|
||||
{
|
||||
int inputOffset = 0;
|
||||
for (int i = 0; i < height; i += 4)
|
||||
{
|
||||
for (int j = 0; j < width; j += 4)
|
||||
{
|
||||
int outputOffset = ((i * width) + j) * Unsafe.SizeOf<ColorRGBA32>();
|
||||
BcHelpers.DecompressBc2(input.Slice(inputOffset), output.Slice(outputOffset), width * 4);
|
||||
inputOffset += DefineConstants.BCDEC_BC2_BLOCK_SIZE;
|
||||
}
|
||||
}
|
||||
RgbConverter.Convert<ColorRGBA32, byte, ColorBGRA32, byte>(output, width, height, output);
|
||||
return inputOffset;
|
||||
}
|
||||
|
||||
public static int DecompressBC3(ReadOnlySpan<byte> input, int width, int height, out byte[] output)
|
||||
{
|
||||
output = new byte[width * height * Unsafe.SizeOf<ColorBGRA32>()];
|
||||
return DecompressBC3(input, width, height, output);
|
||||
}
|
||||
|
||||
public static int DecompressBC3(ReadOnlySpan<byte> input, int width, int height, Span<byte> output)
|
||||
{
|
||||
int inputOffset = 0;
|
||||
for (int i = 0; i < height; i += 4)
|
||||
{
|
||||
for (int j = 0; j < width; j += 4)
|
||||
{
|
||||
int outputOffset = ((i * width) + j) * Unsafe.SizeOf<ColorRGBA32>();
|
||||
BcHelpers.DecompressBc3(input.Slice(inputOffset), output.Slice(outputOffset), width * 4);
|
||||
inputOffset += DefineConstants.BCDEC_BC3_BLOCK_SIZE;
|
||||
}
|
||||
}
|
||||
RgbConverter.Convert<ColorRGBA32, byte, ColorBGRA32, byte>(output, width, height, output);
|
||||
return inputOffset;
|
||||
}
|
||||
|
||||
public static int DecompressBC4(ReadOnlySpan<byte> input, int width, int height, out byte[] output)
|
||||
{
|
||||
output = new byte[width * height * Unsafe.SizeOf<ColorBGRA32>()];
|
||||
return DecompressBC4(input, width, height, output);
|
||||
}
|
||||
|
||||
public static int DecompressBC4(ReadOnlySpan<byte> input, int width, int height, Span<byte> output)
|
||||
{
|
||||
int inputOffset = 0;
|
||||
Span<byte> buffer = new byte[width * height * Unsafe.SizeOf<ColorR8>()];
|
||||
for (int i = 0; i < height; i += 4)
|
||||
{
|
||||
for (int j = 0; j < width; j += 4)
|
||||
{
|
||||
int bufferOffset = ((i * width) + j) * Unsafe.SizeOf<ColorR8>();
|
||||
BcHelpers.DecompressBc4(input.Slice(inputOffset), buffer.Slice(bufferOffset), width);
|
||||
inputOffset += DefineConstants.BCDEC_BC4_BLOCK_SIZE;
|
||||
}
|
||||
}
|
||||
RgbConverter.Convert<ColorR8, byte, ColorBGRA32, byte>(buffer, width, height, output);
|
||||
return inputOffset;
|
||||
}
|
||||
|
||||
public static int DecompressBC5(ReadOnlySpan<byte> input, int width, int height, out byte[] output)
|
||||
{
|
||||
output = new byte[width * height * Unsafe.SizeOf<ColorBGRA32>()];
|
||||
return DecompressBC5(input, width, height, output);
|
||||
}
|
||||
|
||||
public static int DecompressBC5(ReadOnlySpan<byte> input, int width, int height, Span<byte> output)
|
||||
{
|
||||
int inputOffset = 0;
|
||||
Span<byte> buffer = new byte[width * height * Unsafe.SizeOf<ColorRG16>()];
|
||||
for (int i = 0; i < height; i += 4)
|
||||
{
|
||||
for (int j = 0; j < width; j += 4)
|
||||
{
|
||||
int bufferOffset = ((i * width) + j) * Unsafe.SizeOf<ColorRG16>();
|
||||
BcHelpers.DecompressBc5(input.Slice(inputOffset), buffer.Slice(bufferOffset), width * 2);
|
||||
inputOffset += DefineConstants.BCDEC_BC5_BLOCK_SIZE;
|
||||
}
|
||||
}
|
||||
RgbConverter.Convert<ColorRG16, byte, ColorBGRA32, byte>(buffer, width, height, output);
|
||||
return inputOffset;
|
||||
}
|
||||
|
||||
public static int DecompressBC6H(ReadOnlySpan<byte> input, int width, int height, bool isSigned, out byte[] output)
|
||||
{
|
||||
output = new byte[width * height * Unsafe.SizeOf<ColorBGRA32>()];
|
||||
return DecompressBC6H(input, width, height, isSigned, output);
|
||||
}
|
||||
|
||||
public unsafe static int DecompressBC6H(ReadOnlySpan<byte> input, int width, int height, bool isSigned, Span<byte> output)
|
||||
{
|
||||
int bytesRead;
|
||||
byte[] buffer = new byte[width * height * Unsafe.SizeOf<ColorRGBSingle>()];
|
||||
fixed (byte* inputPtr = input)
|
||||
{
|
||||
fixed (byte* bufferPtr = buffer)
|
||||
{
|
||||
bytesRead = DecompressBC6H(inputPtr, width, height, isSigned, bufferPtr);
|
||||
}
|
||||
}
|
||||
RgbConverter.Convert<ColorRGBSingle, float, ColorBGRA32, byte>(buffer, width, height, output);
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
private unsafe static int DecompressBC6H(byte* input, int width, int height, bool isSigned, byte* output)
|
||||
{
|
||||
int inputOffset = 0;
|
||||
for (int i = 0; i < height; i += 4)
|
||||
{
|
||||
for (int j = 0; j < width; j += 4)
|
||||
{
|
||||
int outputOffset = ((i * width) + j) * Unsafe.SizeOf<ColorRGBSingle>();
|
||||
BcHelpers.DecompressBc6h_Float(input + inputOffset, output + outputOffset, width * 3, isSigned ? 1 : 0);
|
||||
inputOffset += DefineConstants.BCDEC_BC6H_BLOCK_SIZE;
|
||||
}
|
||||
}
|
||||
return inputOffset;
|
||||
}
|
||||
|
||||
public static int DecompressBC7(ReadOnlySpan<byte> input, int width, int height, out byte[] output)
|
||||
{
|
||||
output = new byte[width * height * Unsafe.SizeOf<ColorBGRA32>()];
|
||||
return DecompressBC7(input, width, height, output);
|
||||
}
|
||||
|
||||
public unsafe static int DecompressBC7(ReadOnlySpan<byte> input, int width, int height, Span<byte> output)
|
||||
{
|
||||
int bytesRead;
|
||||
fixed (byte* inputPtr = input)
|
||||
{
|
||||
fixed (byte* outputPtr = output)
|
||||
{
|
||||
bytesRead = DecompressBC7(inputPtr, width, height, outputPtr);
|
||||
}
|
||||
}
|
||||
RgbConverter.Convert<ColorRGBA32, byte, ColorBGRA32, byte>(output, width, height, output);
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
private unsafe static int DecompressBC7(byte* input, int width, int height, byte* output)
|
||||
{
|
||||
int inputOffset = 0;
|
||||
for (int i = 0; i < height; i += 4)
|
||||
{
|
||||
for (int j = 0; j < width; j += 4)
|
||||
{
|
||||
int outputOffset = ((i * width) + j) * Unsafe.SizeOf<ColorRGBA32>();
|
||||
BcHelpers.DecompressBc7(input + inputOffset, output + outputOffset, width * 4);
|
||||
inputOffset += DefineConstants.BCDEC_BC7_BLOCK_SIZE;
|
||||
}
|
||||
}
|
||||
return inputOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,45 @@
|
||||
namespace AssetRipper.TextureDecoder.Bc;
|
||||
|
||||
internal struct BitStream
|
||||
{
|
||||
public ulong low;
|
||||
public ulong high;
|
||||
|
||||
public int ReadBits(int numBits)
|
||||
{
|
||||
uint mask = (uint)((1 << numBits) - 1);
|
||||
/* Read the low N bits */
|
||||
uint bits = (uint)(this.low & mask);
|
||||
|
||||
this.low >>= numBits;
|
||||
/* Put the low N bits of "high" into the high 64-N bits of "low". */
|
||||
this.low |= (this.high & mask) << ((sizeof(ulong) * 8) - numBits);
|
||||
this.high >>= numBits;
|
||||
|
||||
return (int)bits;
|
||||
}
|
||||
|
||||
public int ReadBit()
|
||||
{
|
||||
return this.ReadBits(1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reversed bits pulling, used in BC6H decoding
|
||||
/// </summary>
|
||||
/// <param name="numBits"></param>
|
||||
/// <returns></returns>
|
||||
public int ReadBitsReversed(int numBits)
|
||||
{
|
||||
int bits = this.ReadBits(numBits);
|
||||
/* Reverse the bits. */
|
||||
int result = 0;
|
||||
while (numBits-- != 0)
|
||||
{
|
||||
result <<= 1;
|
||||
result |= bits & 1;
|
||||
bits >>= 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace AssetRipper.TextureDecoder.Bc;
|
||||
|
||||
internal static class DefineConstants
|
||||
{
|
||||
public const int BCDEC_BC1_BLOCK_SIZE = 8;
|
||||
public const int BCDEC_BC2_BLOCK_SIZE = 16;
|
||||
public const int BCDEC_BC3_BLOCK_SIZE = 16;
|
||||
public const int BCDEC_BC4_BLOCK_SIZE = 8;
|
||||
public const int BCDEC_BC5_BLOCK_SIZE = 16;
|
||||
public const int BCDEC_BC6H_BLOCK_SIZE = 16;
|
||||
public const int BCDEC_BC7_BLOCK_SIZE = 16;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/* bcdec.h - v0.94
|
||||
provides functions to decompress blocks of BC compressed images
|
||||
written by Sergii "iOrange" Kudlai in 2022
|
||||
This library does not allocate memory and is trying to use as less stack as possible
|
||||
The library was never optimized specifically for speed but for the overall size
|
||||
it has zero external dependencies and is not using any runtime functions
|
||||
Supported BC formats:
|
||||
BC1 (also known as DXT1) + it's "binary alpha" variant BC1A (DXT1A)
|
||||
BC2 (also known as DXT3)
|
||||
BC3 (also known as DXT5)
|
||||
BC4 (also known as ATI1N)
|
||||
BC5 (also known as ATI2N)
|
||||
BC6H (HDR format)
|
||||
BC7
|
||||
BC1/BC2/BC3/BC7 are expected to decompress into 4*4 RGBA blocks 8bit per component (32bit pixel)
|
||||
BC4/BC5 are expected to decompress into 4*4 R/RG blocks 8bit per component (8bit and 16bit pixel)
|
||||
BC6H is expected to decompress into 4*4 RGB blocks of either 32bit float or 16bit "half" per
|
||||
component (96bit or 48bit pixel)
|
||||
For more info, issues and suggestions please visit https://github.com/iOrange/bcdec
|
||||
CREDITS:
|
||||
Aras Pranckevicius (@aras-p) - BC1/BC3 decoders optimizations (up to 3x the speed)
|
||||
- BC6H/BC7 bits pulling routines optimizations
|
||||
- Split BC6H decompression function into 'half' and
|
||||
'float' variants
|
||||
LICENSE: See end of file for license information.
|
||||
*/
|
||||
|
||||
|
||||
/* Used information sources:
|
||||
https://docs.microsoft.com/en-us/windows/win32/direct3d10/d3d10-graphics-programming-guide-resources-block-compression
|
||||
https://docs.microsoft.com/en-us/windows/win32/direct3d11/bc6h-format
|
||||
https://docs.microsoft.com/en-us/windows/win32/direct3d11/bc7-format
|
||||
https://docs.microsoft.com/en-us/windows/win32/direct3d11/bc7-format-mode-reference
|
||||
! WARNING ! Khronos's BPTC partitions tables contain mistakes, do not use them!
|
||||
https://www.khronos.org/registry/DataFormat/specs/1.1/dataformat.1.1.html#BPTC
|
||||
! Use tables from here instead !
|
||||
https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_texture_compression_bptc.txt
|
||||
Leaving it here as it's a nice read
|
||||
https://fgiesen.wordpress.com/2021/10/04/gpu-bcn-decoding/
|
||||
Fast half to float function from here
|
||||
https://gist.github.com/rygorous/2144712
|
||||
*/
|
||||
@@ -0,0 +1,15 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace AssetRipper.TextureDecoder.Bc;
|
||||
|
||||
/// <summary>
|
||||
/// Union between uint and float
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
internal struct FP32
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
public uint u;
|
||||
[FieldOffset(0)]
|
||||
public float f;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
This software is available under 2 licenses -- choose whichever you prefer.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
ALTERNATIVE A - MIT License
|
||||
|
||||
Copyright (c) 2022 Sergii Kudlai
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
ALTERNATIVE B - The Unlicense
|
||||
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <https://unlicense.org>
|
||||
@@ -4,4 +4,6 @@ Managed library for decoding textures
|
||||
|
||||
# Credits
|
||||
|
||||
Forked code from [bcdec](https://github.com/iOrange/bcdec) licensed under the [MIT license](Licenses/bcdec.md)
|
||||
|
||||
Forked code from [uTinyRipper](https://github.com/mafaca/UtinyRipper) licensed under the [MIT license](Licenses/uTinyRipper.md)
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1 @@
|
||||
(� (� (� (� (� (� (� (� )� (� )� )� )�!)� )� )�!)�!)�!)�!)�!)�!)�!*�!)�!)�!)�!*�!*�!*�!*�!*�!*�!*�"*�!*�!*�!*�!*�!*�"*�"*�"+�"+�"+�"+�"+�"+�"+�"+�"+�"+�"+�"+�#,�"+�#,�#,�#,�#,�#,�#,�#,�#,�#,�#,�#,�#,�$-�$-�#-�$-�$-�$-�$-�$-�$-�$-�$-�$-�%.�$.�$.�%.�%.�%.�%.�%.�%/�%.�%/�%/�%/�%/�%/�%/�&/�&/�%/�&0�&/�&/�&0�&0�&0�&0�&0�&0�&0�&0�&1�&1�&1�'1�'1�'1�'1�'1�'1�'2�'2�(2�(2�'2�'2�(2�'2�(3�(3�(3�(3�(3�(3�(3�(3�(3�(3�)4�)4�)4�)4�)4�)4�)4�)4�)4�)4�)5�)5�)5�)5�)5�*5�*5�*5�*5�*6�*6�*6�*6�*6�*6�*6�+6�+6�+7�+6�+7�+7�+7�+7�+7�+7�+7�+7�,7�,8�+7�,8�,8�,7�,8�,8�,8�,8�,8�,8�,8�,8�,9�,9�-9�-9�-9�-9�-9�-9�-9�-9�-:�-9�-:�-:�-:�-:�-:�-:�-:�-:�-:�.:�.:�.:�.:�.:�.;�.;�.;�.;�.;�.;�.;�.;�.;�.;�.;�.;�.;�.;�.;�/;�.;�.;�.;�/<�.<�/<�/<�/<�.<�/<�/<�/<�.<�/<�/<�/<�/<�/<�/<�/<�/<�/<�/<�/<�.<�/<�/<�/<�/<�/<�/<�/<�/<�/<�/<�/<�/<�/<�/<�.<�/<�/<�/<�/<�/<�/<�.<�.;�.;�.;�.;�/<�.;�.;�.;�.;�.;�.;�.;�.;�.;�.;�.;�.;�.;�.;�.:�.;�.;�.:�.:�-:�-:�-:�-:�-:�-:�-:�-:�-:�-:�-:�-:�-:�-9�-9�-9�-9�-9�-9�-9�,9�,9�,8�,8�,8�,8�,8�,8�,8�,8�,8�,7�,8�,8�,8�,8�,7�+7�+7�+7�+7�+7�+7�+7�+7�+6�+7�+7�*6�*6�+6�*6�*6�*6�*6�*6�*5�*5�*5�*5�)5�)5�)5�)5�)5�)5�)5�)5�)4�)4�)4�)4�)4�)4�)4�(3�(3�(3�(3�(3�(3�(3�(3�(2�(2�(3�'2�(2�(2�(2�'2�'1�'2�'1�'1�'1�'1�'1�'1�'1�'1�'1�&0�&0�&0�&0�&0�&0�&0�&0�&0�&/�&/�%/�&/�%/�%/�%/�%/�%/�%/�%.�%/�%/�%.�%.�%.�%.�%.�$.�$.�%.�$.�$-�$-�$-�$-�$-�$-�$-�$-�$-�$-�$,�$-�$,�#,�#,�#,�#,�#,�#,�#,�#,�#,�",�#,�"+�#+�"+�"+�"+�"+�"+�"+�"+�"+�"+�"+�"+�"*�"*�"+�!*�"*�!*�!*�"*�!*�!*�!*�!*�!*�!*�!*�!)�!)�!)�!)�!)�!)�!)�!)�!)�!)�!)� )� )� )� (� )�!(� (� (� (� (� (� (�!(� (� (� (� (� (� (� (� (� (� (� (�!(� )�!)�!)� )� )� )�!)�!)�!)�!)�!)�!)�!)�!)�!*�!*�!*�!*�!*�!*�!*�!*�!*�!*�!*�!*�"*�!*�!*�"+�"*�"+�"*�"*�"+�"+�"+�"+�"+�"+�"+�"+�#,�"+�#,�#,�#,�#,�#,�#,�#,�#,�#,�#,�#,�#,�#,�$-�$-�$-�$-�$-�$-�$-�$-�$-�$-�$.�$-�%.�$.�%.�%.�%.�%.�%.�%.�%.�%/�%/�%/�%/�%/�%/�%/�&/�&/�&/�&/�&/�&/�&0�&0�&0�&0�&0�&0�&0�&0�'1�'1�'1�'1�'1�'1�'1�'1�'2�'2�'2�'2�'2�'2�(2�'2�(3�(3�(2�(3�(3�(3�(3�(3�(3�(3�)3�)4�)4�)4�)4�)4�)4�)4�)5�)5�)5�)5�)5�)5�)5�)5�*5�*5�*5�*5�*6�*6�*6�*6�+6�*6�+6�+6�+6�+7�+6�+7�+7�+7�+7�+7�+7�+7�+7�,7�,8�,8�,8�,8�,8�,7�,8�,8�,8�,8�,8�,9�,8�,8�-9�-9�-9�-9�-9�-9�-9�-9�-9�-:�-9�-:�-:�-:�-:�-:�-:�.:�.:�.:�.:�.:�.:�.:�.;�.;�.;�.;�.:�.;�.;�.;�.;�.;�.;�.;�.;�.;�.;�.<�.;�.;�.;�.;�.;�/<�.<�.;�/<�/<�/<�/<�/<�/<�/<�/<�/<�/<�/<�/<�/<�/<�/<�.<�/<�/<�/<�/<�/<�/<�/<�/<�/<�/<�/<�/<�/<�/<�/<�/<�/<�/<�/<�/<�/<�/<�/<�.<�.<�.;�.;�.;�.;�.;�.;�.;�.;�.;�.;�.;�.;�.;�.;�.;�.;�.;�.;�.:�.;�.;�.:�.:�-:�-:�-:�-:�-:�-:�-:�-:�-:�-:�-:�-:�-9�-9�-9�-9�-9�-9�-9�,9�,9�,8�,8�,8�,9�,8�,8�,8�,8�,8�,8�,7�,7�,8�,8�,7�,7�+7�+7�+7�+7�+7�+7�+7�+7�+7�+6�+7�+7�+6�*6�*6�*6�*6�*6�*6�*6�*5�*5�*5�*5�)5�)5�)5�)5�)5�)4�)4�)4�)4�)4�)4�)4�)4�)4�)3�(3�(3�(3�(3�(3�(3�(3�(3�(2�(2�(2�'2�'2�'2�'2�'2�'2�'2�'1�'1�'1�'1�'1�&0�'1�'1�&1�'0�&0�&0�&0�&0�&0�&0�&/�&/�&/�%/�&/�&/�%/�%/�%/�%/�%/�%.�%.�%/�%.�%.�%.�%.�%.�$.�%.�$.�$-�$.�$.�$-�$-�$-�$-�$-�#-�$-�$-�$-�#-�#,�#,�#,�#,�#,�#,�#,�#,�#,�#,�#,�",�#,�#+�",�"+�"+�"+�"+�"+�"+�"+�"+�"+�"+�"*�!*�!*�!*�!*�!*�!*�!*�!*�!*�!*�!*�!*�!*�!)�!)�!)� )�!)�!)�!)�!)�!)�!)�!)�!)�!)�!)�!)�!)� )�!(� (� )� (� (� (� (� (� (� (� (� (� (� (� (� (� (� (� (�!)� )�!)� )� )�!)�!)�!)�!)�!)�!)�!)�!)�!*�!)�!)�!*�!*�!*�!*�!*�!*�!*�!*�!*�!*�!*�!*�!*�!*�"*�"*�"+�"+�"+�"+�"+�"+�"+�"+�"+�"+�"+�"+�"+�",�#,�#,�#,�#,�#,�#,�#,�#,�#,�#,�#,�#,�$-�$-�$-�$-�$-�$-�$-�$-�$-�$-�$.�$-�$.�$.�$.�$.�%.�%.�%.�%.�%/�%/�%/�%/�%/�%/�%/�&/�&/�&/�&/�&/�&/�&0�&0�&0�&0�&0�&0�&0�&0�&0�'1�&1�'1�'1�'1�'1�'1�'2�'2�'2�'2�(2�'2�'2�'2�(3�(2�(2�(3�(3�(3�(3�(3�(3�(3�(3�)4�)4�)4�)4�)4�)4�)4�)4�)4�)5�)4�)4�)5�)5�*5�*5�)5�*5�*5�*5�*6�*6�*6�*6�*6�*6�*6�+6�*6�+7�+7�+7�+7�+7�+7�+7�+7�+7�+7�,7�,8�,8�,8�,8�,8�,8�,8�,8�,8�,8�,9�-9�,8�,8�,9�,9�,9�-9�-9�-9�-9�-9�-9�-9�-9�-:�-:�-:�-:�-:�-:�-:�-:�-:�-:�.:�.:�.:�.;�.;�.:�.:�.;�.;�.;�.;�.;�.;�.;�.;�.Line truncated
|
||||
+2
-1
@@ -17,6 +17,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Workflows", "Workflows", "{
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Licenses", "Licenses", "{0BFF6817-43C8-43EE-8EE8-1A03B7ECEA1A}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
Licenses\bcdec.md = Licenses\bcdec.md
|
||||
Licenses\uTinyRipper.md = Licenses\uTinyRipper.md
|
||||
EndProjectSection
|
||||
EndProject
|
||||
@@ -26,7 +27,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AssetRipper.TextureDecoder"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AssetRipper.TextureDecoder.TestGenerator", "AssetRipper.TextureDecoder.TestGenerator\AssetRipper.TextureDecoder.TestGenerator.csproj", "{0074908C-35A8-4C71-8F74-A83A4095ACEA}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetRipper.TextureDecoder.ConsoleApp", "AssetRipper.TextureDecoder.ConsoleApp\AssetRipper.TextureDecoder.ConsoleApp.csproj", "{FFC8EEF8-8BF1-4B65-ADDA-A949EDDF4CB4}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AssetRipper.TextureDecoder.ConsoleApp", "AssetRipper.TextureDecoder.ConsoleApp\AssetRipper.TextureDecoder.ConsoleApp.csproj", "{FFC8EEF8-8BF1-4B65-ADDA-A949EDDF4CB4}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AssetRipper.TextureDecoder.Benchmarks", "AssetRipper.TextureDecoder.Benchmarks\AssetRipper.TextureDecoder.Benchmarks.csproj", "{F85804F4-4864-412E-BDC6-8B6E2B5646A7}"
|
||||
EndProject
|
||||
|
||||
Reference in new issue
Block a user