@@ -10,17 +10,30 @@ namespace SixLabors.ImageSharp.Textures.TextureFormats.Decoding;
1010/// </summary>
1111internal static class AstcDecoder
1212{
13+ internal const int AstcBlockSize = 16 ;
14+
1315 /// <summary>
1416 /// Decodes an ASTC block into RGBA pixels.
1517 /// </summary>
1618 /// <param name="blockData">The 16-byte ASTC block data.</param>
1719 /// <param name="blockWidth">The width of the block footprint (4-12).</param>
1820 /// <param name="blockHeight">The height of the block footprint (4-12).</param>
1921 /// <param name="decodedPixels">The output span for decoded RGBA pixels.</param>
20- /// <param name="isSrgb">Optional flag to indicate if the output should be in sRGB color space .</param >
22+ /// <exception cref="ArgumentException">Thrown if blockData is not 16 bytes or decodedPixels is the wrong size .</exception >
2123 /// <exception cref="ArgumentOutOfRangeException">Thrown if the block dimensions are invalid.</exception>
22- public static void DecodeBlock ( ReadOnlySpan < byte > blockData , int blockWidth , int blockHeight , Span < byte > decodedPixels , bool isSrgb = false )
24+ public static void DecodeBlock ( ReadOnlySpan < byte > blockData , int blockWidth , int blockHeight , Span < byte > decodedPixels )
2325 {
26+ if ( blockData . Length != AstcBlockSize )
27+ {
28+ throw new ArgumentException ( $ "ASTC block data must be exactly { AstcBlockSize } bytes. Received { blockData . Length } bytes.", nameof ( blockData ) ) ;
29+ }
30+
31+ int expectedDecodedSize = blockWidth * blockHeight * 4 ;
32+ if ( decodedPixels . Length < expectedDecodedSize )
33+ {
34+ throw new ArgumentException ( $ "Output buffer must be at least { expectedDecodedSize } bytes for { blockWidth } x{ blockHeight } block. Received { decodedPixels . Length } bytes.", nameof ( decodedPixels ) ) ;
35+ }
36+
2437 Footprint footprint = Footprint . FromFootprintType ( FootprintFromDimensions ( blockWidth , blockHeight ) ) ;
2538
2639 AstcSharp . AstcDecoder . DecompressBlock ( blockData , footprint , decodedPixels ) ;
@@ -36,6 +49,9 @@ public static void DecodeBlock(ReadOnlySpan<byte> blockData, int blockWidth, int
3649 /// <param name="blockHeight">The height of the block footprint.</param>
3750 /// <param name="compressedBytesPerBlock">The number of compressed bytes per block.</param>
3851 /// <returns>The decompressed RGBA pixel data.</returns>
52+ /// <exception cref="ArgumentNullException">Thrown if blockData is null.</exception>
53+ /// <exception cref="ArgumentOutOfRangeException">Thrown if dimensions or block parameters are invalid.</exception>
54+ /// <exception cref="ArgumentException">Thrown if blockData length is invalid.</exception>
3955 public static byte [ ] DecompressImage (
4056 byte [ ] blockData ,
4157 int width ,
@@ -44,8 +60,28 @@ public static byte[] DecompressImage(
4460 int blockHeight ,
4561 byte compressedBytesPerBlock )
4662 {
63+ ArgumentNullException . ThrowIfNull ( blockData ) ;
64+ ArgumentOutOfRangeException . ThrowIfLessThanOrEqual ( 0 , width ) ;
65+ ArgumentOutOfRangeException . ThrowIfLessThanOrEqual ( 0 , height ) ;
66+
67+ if ( compressedBytesPerBlock != AstcBlockSize )
68+ {
69+ throw new ArgumentOutOfRangeException ( nameof ( compressedBytesPerBlock ) , compressedBytesPerBlock , $ "ASTC blocks must be { AstcBlockSize } bytes.") ;
70+ }
71+
72+ // Validate block dimensions (will throw if invalid)
73+ _ = FootprintFromDimensions ( blockWidth , blockHeight ) ;
74+
4775 int blocksWide = ( width + blockWidth - 1 ) / blockWidth ;
4876 int blocksHigh = ( height + blockHeight - 1 ) / blockHeight ;
77+ int totalBlocks = blocksWide * blocksHigh ;
78+ int expectedDataLength = totalBlocks * compressedBytesPerBlock ;
79+
80+ if ( blockData . Length < expectedDataLength )
81+ {
82+ throw new ArgumentException ( $ "Block data is too small. Expected at least { expectedDataLength } bytes for { width } x{ height } texture with { blockWidth } x{ blockHeight } blocks, but received { blockData . Length } bytes.", nameof ( blockData ) ) ;
83+ }
84+
4985 byte [ ] decompressedData = new byte [ width * height * 4 ] ;
5086 byte [ ] decodedBlock = new byte [ blockWidth * blockHeight * 4 ] ;
5187
@@ -105,6 +141,6 @@ private static FootprintType FootprintFromDimensions(int width, int height)
105141 ( 10 , 10 ) => FootprintType . Footprint10x10 ,
106142 ( 12 , 10 ) => FootprintType . Footprint12x10 ,
107143 ( 12 , 12 ) => FootprintType . Footprint12x12 ,
108- _ => throw new ArgumentOutOfRangeException ( nameof ( width ) , "Invalid footprint type ." ) ,
144+ _ => throw new ArgumentOutOfRangeException ( nameof ( width ) , $ "Invalid ASTC block dimensions: { width } x { height } . Valid sizes are 4x4, 5x4, 5x5, 6x5, 6x6, 8x5, 8x6, 8x8, 10x5, 10x6, 10x8, 10x10, 12x10, 12x12 .") ,
109145 } ;
110146}
0 commit comments