1+ using AssetRipper . TextureDecoder . Rgb ;
2+ using AssetRipper . TextureDecoder . Rgb . Formats ;
13using System . Buffers . Binary ;
24
35namespace AssetRipper . TextureDecoder . Astc
@@ -12,51 +14,58 @@ private static void ValidateBlockDimension(int value, [CallerArgumentExpression(
1214 }
1315 }
1416
15- public static int DecodeASTC ( ReadOnlySpan < byte > input , int width , int height , int blockWidth , int blockHeight , out byte [ ] output )
17+ public static int DecodeASTC < TOutputColor , TOutputChannelValue > ( ReadOnlySpan < byte > input , int width , int height , int blockWidth , int blockHeight , out byte [ ] output )
18+ where TOutputChannelValue : unmanaged
19+ where TOutputColor : unmanaged, IColor < TOutputChannelValue >
1620 {
1721 output = new byte [ width * height * 4 ] ;
18- return DecodeASTC ( input , width , height , blockWidth , blockHeight , output ) ;
22+ return DecodeASTC < TOutputColor , TOutputChannelValue > ( input , width , height , blockWidth , blockHeight , output ) ;
1923 }
2024
21- public static int DecodeASTC ( ReadOnlySpan < byte > input , int width , int height , int blockWidth , int blockHeight , Span < byte > output )
25+ public static int DecodeASTC < TOutputColor , TOutputChannelValue > ( ReadOnlySpan < byte > input , int width , int height , int blockWidth , int blockHeight , Span < byte > output )
26+ where TOutputChannelValue : unmanaged
27+ where TOutputColor : unmanaged, IColor < TOutputChannelValue >
2228 {
29+ ThrowHelper . ThrowIfNotLittleEndian ( ) ;
30+ return DecodeASTC < TOutputColor , TOutputChannelValue > ( input , width , height , blockWidth , blockHeight , MemoryMarshal . Cast < byte , TOutputColor > ( output ) ) ;
31+ }
32+
33+ public static int DecodeASTC < TOutputColor , TOutputChannelValue > ( ReadOnlySpan < byte > input , int width , int height , int blockWidth , int blockHeight , Span < TOutputColor > output )
34+ where TOutputChannelValue : unmanaged
35+ where TOutputColor : unmanaged, IColor < TOutputChannelValue >
36+ {
37+ ThrowHelper . ThrowIfNotEnoughSpace ( output . Length , width * height ) ;
2338 ValidateBlockDimension ( blockWidth ) ;
2439 ValidateBlockDimension ( blockHeight ) ;
2540 int bcw = ( width + blockWidth - 1 ) / blockWidth ;
2641 int bch = ( height + blockHeight - 1 ) / blockHeight ;
2742 int clen_last = ( width + blockWidth - 1 ) % blockWidth + 1 ;
28- Span < uint > buf = stackalloc uint [ blockWidth * blockHeight ] ;
43+ Span < ColorRGBA < byte > > buffer = stackalloc ColorRGBA < byte > [ blockWidth * blockHeight ] ;
2944 int inputOffset = 0 ;
3045 for ( int t = 0 ; t < bch ; t ++ )
3146 {
3247 for ( int s = 0 ; s < bcw ; s ++ , inputOffset += 16 )
3348 {
34- DecodeBlock ( input [ inputOffset ..] , blockWidth , blockHeight , buf ) ;
49+ DecodeBlock ( input [ inputOffset ..] , blockWidth , blockHeight , buffer ) ;
3550 int clen = s < bcw - 1 ? blockWidth : clen_last ;
3651 for ( int i = 0 , y = t * blockHeight ; i < blockHeight && y < height ; i ++ , y ++ )
3752 {
3853 int outputOffsetUInt32 = t * blockHeight * width + s * blockWidth + i * width ;
3954 for ( int j = 0 ; j < clen ; j ++ )
4055 {
41- WriteUInt32 ( output , outputOffsetUInt32 + j , buf [ j + i * blockWidth ] ) ;
56+ output [ outputOffsetUInt32 + j ] = buffer [ j + i * blockWidth ] . Convert < ColorRGBA < byte > , byte , TOutputColor , TOutputChannelValue > ( ) ;
4257 }
4358 }
4459 }
4560 }
4661 return inputOffset ;
47-
48- [ MethodImpl ( MethodImplOptions . AggressiveInlining | MethodImplOptions . AggressiveOptimization ) ]
49- static void WriteUInt32 ( Span < byte > buffer , int offsetUInt32 , uint value )
50- {
51- BinaryPrimitives . WriteUInt32LittleEndian ( buffer . Slice ( offsetUInt32 * sizeof ( uint ) ) , value ) ;
52- }
5362 }
5463
55- private static void DecodeBlock ( ReadOnlySpan < byte > input , int blockWidth , int blockHeight , Span < uint > output )
64+ private static void DecodeBlock ( ReadOnlySpan < byte > input , int blockWidth , int blockHeight , Span < ColorRGBA < byte > > output )
5665 {
5766 if ( input [ 0 ] == 0xfc && ( input [ 1 ] & 1 ) == 1 )
5867 {
59- uint c = Color ( input [ 9 ] , input [ 11 ] , input [ 13 ] , input [ 15 ] ) ;
68+ ColorRGBA < byte > c = new ( input [ 9 ] , input [ 11 ] , input [ 13 ] , input [ 15 ] ) ;
6069 for ( int i = 0 ; i < blockWidth * blockHeight ; i ++ )
6170 {
6271 output [ i ] = c ;
@@ -674,7 +683,7 @@ private static void SelectPartition(ReadOnlySpan<byte> input, ref BlockData bloc
674683 }
675684 }
676685
677- private static void ApplicateColor ( BlockData block , Span < uint > output )
686+ private static void ApplicateColor ( BlockData block , Span < ColorRGBA < byte > > output )
678687 {
679688 if ( block . dual_plane != 0 )
680689 {
@@ -689,7 +698,7 @@ private static void ApplicateColor(BlockData block, Span<uint> output)
689698 byte g = SelectColor ( block . endpoints [ p ] [ 1 ] , block . endpoints [ p ] [ 5 ] , block . weights [ i * 2 + ps [ 1 ] ] ) ;
690699 byte b = SelectColor ( block . endpoints [ p ] [ 2 ] , block . endpoints [ p ] [ 6 ] , block . weights [ i * 2 + ps [ 2 ] ] ) ;
691700 byte a = SelectColor ( block . endpoints [ p ] [ 3 ] , block . endpoints [ p ] [ 7 ] , block . weights [ i * 2 + ps [ 3 ] ] ) ;
692- output [ i ] = Color ( r , g , b , a ) ;
701+ output [ i ] = new ( r , g , b , a ) ;
693702 }
694703 }
695704 else
@@ -700,7 +709,7 @@ private static void ApplicateColor(BlockData block, Span<uint> output)
700709 byte g = SelectColor ( block . endpoints [ 0 ] [ 1 ] , block . endpoints [ 0 ] [ 5 ] , block . weights [ i * 2 + ps [ 1 ] ] ) ;
701710 byte b = SelectColor ( block . endpoints [ 0 ] [ 2 ] , block . endpoints [ 0 ] [ 6 ] , block . weights [ i * 2 + ps [ 2 ] ] ) ;
702711 byte a = SelectColor ( block . endpoints [ 0 ] [ 3 ] , block . endpoints [ 0 ] [ 7 ] , block . weights [ i * 2 + ps [ 3 ] ] ) ;
703- output [ i ] = Color ( r , g , b , a ) ;
712+ output [ i ] = new ( r , g , b , a ) ;
704713 }
705714 }
706715 }
@@ -713,7 +722,7 @@ private static void ApplicateColor(BlockData block, Span<uint> output)
713722 byte g = SelectColor ( block . endpoints [ p ] [ 1 ] , block . endpoints [ p ] [ 5 ] , block . weights [ i * 2 ] ) ;
714723 byte b = SelectColor ( block . endpoints [ p ] [ 2 ] , block . endpoints [ p ] [ 6 ] , block . weights [ i * 2 ] ) ;
715724 byte a = SelectColor ( block . endpoints [ p ] [ 3 ] , block . endpoints [ p ] [ 7 ] , block . weights [ i * 2 ] ) ;
716- output [ i ] = Color ( r , g , b , a ) ;
725+ output [ i ] = new ( r , g , b , a ) ;
717726 }
718727 }
719728 else
@@ -724,7 +733,7 @@ private static void ApplicateColor(BlockData block, Span<uint> output)
724733 byte g = SelectColor ( block . endpoints [ 0 ] [ 1 ] , block . endpoints [ 0 ] [ 5 ] , block . weights [ i * 2 ] ) ;
725734 byte b = SelectColor ( block . endpoints [ 0 ] [ 2 ] , block . endpoints [ 0 ] [ 6 ] , block . weights [ i * 2 ] ) ;
726735 byte a = SelectColor ( block . endpoints [ 0 ] [ 3 ] , block . endpoints [ 0 ] [ 7 ] , block . weights [ i * 2 ] ) ;
727- output [ i ] = Color ( r , g , b , a ) ;
736+ output [ i ] = new ( r , g , b , a ) ;
728737 }
729738 }
730739 }
@@ -849,12 +858,6 @@ private static void DecodeIntseq(ReadOnlySpan<byte> input, int offset, int a, in
849858 }
850859 }
851860
852- [ MethodImpl ( MethodImplOptions . AggressiveInlining | MethodImplOptions . AggressiveOptimization ) ]
853- private static uint Color ( uint r , uint g , uint b , uint a )
854- {
855- return r << 16 | g << 8 | b | a << 24 ;
856- }
857-
858861 [ MethodImpl ( MethodImplOptions . AggressiveInlining | MethodImplOptions . AggressiveOptimization ) ]
859862 private static byte BitReverseU8 ( byte c , int bits )
860863 {
0 commit comments