1+ using AssetRipper . TextureDecoder . Rgb ;
12using System . Buffers . Binary ;
23
34namespace AssetRipper . TextureDecoder . Atc
45{
56 public static class AtcDecoder
67 {
7- public static int DecompressAtcRgb4 ( ReadOnlySpan < byte > input , int width , int height , out byte [ ] output )
8+ public static int DecompressAtcRgb4 < TOutputColor , TOutputChannelValue > ( ReadOnlySpan < byte > input , int width , int height , out byte [ ] output )
9+ where TOutputChannelValue : unmanaged
10+ where TOutputColor : unmanaged, IColor < TOutputChannelValue >
811 {
9- output = new byte [ width * height * 4 ] ;
10- return DecompressAtcRgb4 ( input , width , height , output ) ;
12+ output = new byte [ width * height * Unsafe . SizeOf < TOutputColor > ( ) ] ;
13+ return DecompressAtcRgb4 < TOutputColor , TOutputChannelValue > ( input , width , height , output ) ;
1114 }
1215
13- public static int DecompressAtcRgb4 ( ReadOnlySpan < byte > input , int width , int height , Span < byte > output )
16+ public static int DecompressAtcRgb4 < TOutputColor , TOutputChannelValue > ( ReadOnlySpan < byte > input , int width , int height , Span < byte > output )
17+ where TOutputChannelValue : unmanaged
18+ where TOutputColor : unmanaged, IColor < TOutputChannelValue >
1419 {
20+ ThrowHelper . ThrowIfNotLittleEndian ( ) ;
21+ return DecompressAtcRgb4 < TOutputColor , TOutputChannelValue > ( input , width , height , MemoryMarshal . Cast < byte , TOutputColor > ( output ) ) ;
22+ }
23+
24+ public static int DecompressAtcRgb4 < TOutputColor , TOutputChannelValue > ( ReadOnlySpan < byte > input , int width , int height , Span < TOutputColor > output )
25+ where TOutputChannelValue : unmanaged
26+ where TOutputColor : unmanaged, IColor < TOutputChannelValue >
27+ {
28+ ThrowHelper . ThrowIfNotEnoughSpace ( output . Length , width * height ) ;
1529 int bcw = ( width + 3 ) / 4 ;
1630 int bch = ( height + 3 ) / 4 ;
1731 int clen_last = ( width + 3 ) % 4 + 1 ;
18- Span < uint > buf = stackalloc uint [ 16 ] ;
32+ Span < TOutputColor > buf = stackalloc TOutputColor [ 16 ] ;
1933 int inputOffset = 0 ;
2034 for ( int t = 0 ; t < bch ; t ++ )
2135 {
2236 for ( int s = 0 ; s < bcw ; s ++ , inputOffset += 8 )
2337 {
24- DecodeAtcRgb4Block ( input . Slice ( inputOffset , 8 ) , buf ) ;
38+ DecodeAtcRgb4Block < TOutputColor , TOutputChannelValue > ( input . Slice ( inputOffset , 8 ) , buf ) ;
2539 int clen = s < bcw - 1 ? 4 : clen_last ;
2640 for ( int i = 0 , y = t * 4 ; i < 4 && y < height ; i ++ , y ++ )
2741 {
28- int outputOffset = t * 16 * width + s * 16 + i * width * sizeof ( uint ) ;
42+ int outputOffset = t * 4 * width + s * 4 + i * width ;
2943 for ( int j = 0 ; j < clen ; j ++ )
3044 {
31- BinaryPrimitives . WriteUInt32LittleEndian ( output . Slice ( outputOffset + j * sizeof ( uint ) ) , buf [ j + 4 * i ] ) ;
45+ output [ outputOffset + j ] = buf [ j + 4 * i ] ;
3246 }
3347 }
3448 }
3549 }
3650 return inputOffset ;
3751 }
3852
39- public static int DecompressAtcRgba8 ( ReadOnlySpan < byte > input , int width , int height , out byte [ ] output )
53+ public static int DecompressAtcRgba8 < TOutputColor , TOutputChannelValue > ( ReadOnlySpan < byte > input , int width , int height , out byte [ ] output )
54+ where TOutputChannelValue : unmanaged
55+ where TOutputColor : unmanaged, IColor < TOutputChannelValue >
56+ {
57+ output = new byte [ width * height * Unsafe . SizeOf < TOutputColor > ( ) ] ;
58+ return DecompressAtcRgba8 < TOutputColor , TOutputChannelValue > ( input , width , height , output ) ;
59+ }
60+
61+ public static int DecompressAtcRgba8 < TOutputColor , TOutputChannelValue > ( ReadOnlySpan < byte > input , int width , int height , Span < byte > output )
62+ where TOutputChannelValue : unmanaged
63+ where TOutputColor : unmanaged, IColor < TOutputChannelValue >
4064 {
41- output = new byte [ width * height * 4 ] ;
42- return DecompressAtcRgba8 ( input , width , height , output ) ;
65+ ThrowHelper . ThrowIfNotLittleEndian ( ) ;
66+ return DecompressAtcRgba8 < TOutputColor , TOutputChannelValue > ( input , width , height , MemoryMarshal . Cast < byte , TOutputColor > ( output ) ) ;
4367 }
4468
45- public static int DecompressAtcRgba8 ( ReadOnlySpan < byte > input , int width , int height , Span < byte > output )
69+ public static int DecompressAtcRgba8 < TOutputColor , TOutputChannelValue > ( ReadOnlySpan < byte > input , int width , int height , Span < TOutputColor > output )
70+ where TOutputChannelValue : unmanaged
71+ where TOutputColor : unmanaged, IColor < TOutputChannelValue >
4672 {
73+ ThrowHelper . ThrowIfNotEnoughSpace ( output . Length , width * height ) ;
4774 int bcw = ( width + 3 ) / 4 ;
4875 int bch = ( height + 3 ) / 4 ;
4976 int clen_last = ( width + 3 ) % 4 + 1 ;
50- Span < uint > buf = stackalloc uint [ 16 ] ;
77+ Span < TOutputColor > buf = stackalloc TOutputColor [ 16 ] ;
5178 int inputOffset = 0 ;
5279 for ( int t = 0 ; t < bch ; t ++ )
5380 {
5481 for ( int s = 0 ; s < bcw ; s ++ , inputOffset += 16 )
5582 {
56- DecodeAtcRgba8Block ( input . Slice ( inputOffset , 16 ) , buf ) ;
83+ DecodeAtcRgba8Block < TOutputColor , TOutputChannelValue > ( input . Slice ( inputOffset , 16 ) , buf ) ;
5784 int clen = s < bcw - 1 ? 4 : clen_last ;
5885 for ( int i = 0 , y = t * 4 ; i < 4 && y < height ; i ++ , y ++ )
5986 {
60- int outputOffset = t * 16 * width + s * 16 + i * width * sizeof ( uint ) ;
87+ int outputOffset = t * 4 * width + s * 4 + i * width ;
6188 for ( int j = 0 ; j < clen ; j ++ )
6289 {
63- BinaryPrimitives . WriteUInt32LittleEndian ( output . Slice ( outputOffset + j * sizeof ( uint ) ) , buf [ j + 4 * i ] ) ;
90+ output [ outputOffset + j ] = buf [ j + 4 * i ] ;
6491 }
6592 }
6693 }
6794 }
6895 return inputOffset ;
6996 }
7097
71- private static void DecodeAtcRgb4Block ( ReadOnlySpan < byte > input , Span < uint > output )
98+ private static void DecodeAtcRgb4Block < TOutputColor , TOutputChannelValue > ( ReadOnlySpan < byte > input , Span < TOutputColor > output )
99+ where TOutputChannelValue : unmanaged
100+ where TOutputColor : unmanaged, IColor < TOutputChannelValue >
72101 {
73102 Span < int > colors = stackalloc int [ 16 ] ;
74103 int c0 = input . ReadAtOffset < ushort > ( 0 ) ;
@@ -83,12 +112,14 @@ private static void DecodeAtcRgb4Block(ReadOnlySpan<byte> input, Span<uint> outp
83112 int cb = colors [ cidx * 4 + 0 ] ;
84113 int cg = colors [ cidx * 4 + 1 ] ;
85114 int cr = colors [ cidx * 4 + 2 ] ;
86- output [ i ] = Color ( cr , cg , cb , 255 ) ;
115+ output [ i ] . SetConvertedChannels < TOutputColor , TOutputChannelValue , byte > ( ( byte ) cr , ( byte ) cg , ( byte ) cb , byte . MaxValue ) ;
87116 cindex >>= 2 ;
88117 }
89118 }
90119
91- private static void DecodeAtcRgba8Block ( ReadOnlySpan < byte > input , Span < uint > output )
120+ private static void DecodeAtcRgba8Block < TOutputColor , TOutputChannelValue > ( ReadOnlySpan < byte > input , Span < TOutputColor > output )
121+ where TOutputChannelValue : unmanaged
122+ where TOutputColor : unmanaged, IColor < TOutputChannelValue >
92123 {
93124 Span < int > alphas = stackalloc int [ 16 ] ;
94125 ulong avalue = BinaryPrimitives . ReadUInt64LittleEndian ( input ) ;
@@ -112,7 +143,7 @@ private static void DecodeAtcRgba8Block(ReadOnlySpan<byte> input, Span<uint> out
112143 int cr = colors [ cidx * 4 + 2 ] ;
113144 int aidx = unchecked ( ( int ) aindex & 7 ) ;
114145 int ca = alphas [ aidx ] ;
115- output [ i ] = Color ( cr , cg , cb , ca ) ;
146+ output [ i ] . SetConvertedChannels < TOutputColor , TOutputChannelValue , byte > ( ( byte ) cr , ( byte ) cg , ( byte ) cb , ( byte ) ca ) ;
116147 cindex >>= 2 ;
117148 aindex >>= 3 ;
118149 }
@@ -160,9 +191,9 @@ private static void DecodeColors(Span<int> colors, int c0, int c1)
160191 colors [ 13 ] = Extend ( ( c1 >> 5 ) & 0x3F , 6 , 8 ) ;
161192 colors [ 14 ] = Extend ( ( c1 >> 11 ) & 0x1F , 5 , 8 ) ;
162193
163- colors [ 4 ] = Math . Max ( 0 , colors [ 8 ] - colors [ 12 ] / 4 ) ;
164- colors [ 5 ] = Math . Max ( 0 , colors [ 9 ] - colors [ 13 ] / 4 ) ;
165- colors [ 6 ] = Math . Max ( 0 , colors [ 10 ] - colors [ 14 ] / 4 ) ;
194+ colors [ 4 ] = int . Max ( 0 , colors [ 8 ] - colors [ 12 ] / 4 ) ;
195+ colors [ 5 ] = int . Max ( 0 , colors [ 9 ] - colors [ 13 ] / 4 ) ;
196+ colors [ 6 ] = int . Max ( 0 , colors [ 10 ] - colors [ 14 ] / 4 ) ;
166197 }
167198 }
168199
@@ -197,11 +228,5 @@ private static int Extend(int value, int from, int to)
197228 // bit-pattern replicating scaling (can at most double the bits)
198229 return ( value << ( to - from ) ) | ( value >> ( from * 2 - to ) ) ;
199230 }
200-
201- [ MethodImpl ( MethodImplOptions . AggressiveInlining | MethodImplOptions . AggressiveOptimization ) ]
202- private static uint Color ( int r , int g , int b , int a )
203- {
204- return unchecked ( ( uint ) ( r << 16 | g << 8 | b | a << 24 ) ) ;
205- }
206231 }
207232}
0 commit comments