@@ -75,7 +75,7 @@ public TgaDecoderCore(Configuration configuration, ITgaDecoderOptions options)
7575 /// <summary>
7676 /// Gets the dimensions of the image.
7777 /// </summary>
78- public Size Dimensions => new Size ( this . fileHeader . Width , this . fileHeader . Height ) ;
78+ public Size Dimensions => new ( this . fileHeader . Width , this . fileHeader . Height ) ;
7979
8080 /// <inheritdoc />
8181 public Image < TPixel > Decode < TPixel > ( BufferedReadStream stream , CancellationToken cancellationToken )
@@ -87,7 +87,7 @@ public Image<TPixel> Decode<TPixel>(BufferedReadStream stream, CancellationToken
8787 this . currentStream . Skip ( this . fileHeader . IdLength ) ;
8888
8989 // Parse the color map, if present.
90- if ( this . fileHeader . ColorMapType != 0 && this . fileHeader . ColorMapType != 1 )
90+ if ( this . fileHeader . ColorMapType is not 0 and not 1 )
9191 {
9292 TgaThrowHelper . ThrowNotSupportedException ( $ "Unknown tga colormap type { this . fileHeader . ColorMapType } found") ;
9393 }
@@ -117,7 +117,11 @@ public Image<TPixel> Decode<TPixel>(BufferedReadStream stream, CancellationToken
117117 using ( IMemoryOwner < byte > palette = this . memoryAllocator . Allocate < byte > ( colorMapSizeInBytes , AllocationOptions . Clean ) )
118118 {
119119 Span < byte > paletteSpan = palette . GetSpan ( ) ;
120- this . currentStream . Read ( paletteSpan , this . fileHeader . CMapStart , colorMapSizeInBytes ) ;
120+ int bytesRead = this . currentStream . Read ( paletteSpan , this . fileHeader . CMapStart , colorMapSizeInBytes ) ;
121+ if ( bytesRead != colorMapSizeInBytes )
122+ {
123+ TgaThrowHelper . ThrowInvalidImageContentException ( "Not enough data to read the color map" ) ;
124+ }
121125
122126 if ( this . fileHeader . ImageType == TgaImageType . RleColorMapped )
123127 {
@@ -308,8 +312,7 @@ private void ReadPaletted<TPixel>(int width, int height, Buffer2D<TPixel> pixels
308312 private void ReadPalettedRle < TPixel > ( int width , int height , Buffer2D < TPixel > pixels , Span < byte > palette , int colorMapPixelSizeInBytes , TgaImageOrigin origin )
309313 where TPixel : unmanaged, IPixel < TPixel >
310314 {
311- int bytesPerPixel = 1 ;
312- using ( IMemoryOwner < byte > buffer = this . memoryAllocator . Allocate < byte > ( width * height * bytesPerPixel , AllocationOptions . Clean ) )
315+ using ( IMemoryOwner < byte > buffer = this . memoryAllocator . Allocate < byte > ( width * height , AllocationOptions . Clean ) )
313316 {
314317 TPixel color = default ;
315318 Span < byte > bufferSpan = buffer . GetSpan ( ) ;
@@ -319,7 +322,7 @@ private void ReadPalettedRle<TPixel>(int width, int height, Buffer2D<TPixel> pix
319322 {
320323 int newY = InvertY ( y , height , origin ) ;
321324 Span < TPixel > pixelRow = pixels . DangerousGetRowSpan ( newY ) ;
322- int rowStartIdx = y * width * bytesPerPixel ;
325+ int rowStartIdx = y * width ;
323326 for ( int x = 0 ; x < width ; x ++ )
324327 {
325328 int idx = rowStartIdx + x ;
@@ -418,7 +421,12 @@ private void ReadBgra16<TPixel>(int width, int height, Buffer2D<TPixel> pixels,
418421 {
419422 for ( int x = width - 1 ; x >= 0 ; x -- )
420423 {
421- this . currentStream . Read ( this . scratchBuffer , 0 , 2 ) ;
424+ int bytesRead = this . currentStream . Read ( this . scratchBuffer , 0 , 2 ) ;
425+ if ( bytesRead != 2 )
426+ {
427+ TgaThrowHelper . ThrowInvalidImageContentException ( "Not enough data to read a pixel row" ) ;
428+ }
429+
422430 if ( ! this . hasAlpha )
423431 {
424432 this . scratchBuffer [ 1 ] |= 1 << 7 ;
@@ -438,7 +446,11 @@ private void ReadBgra16<TPixel>(int width, int height, Buffer2D<TPixel> pixels,
438446 }
439447 else
440448 {
441- this . currentStream . Read ( rowSpan ) ;
449+ int bytesRead = this . currentStream . Read ( rowSpan ) ;
450+ if ( bytesRead != rowSpan . Length )
451+ {
452+ TgaThrowHelper . ThrowInvalidImageContentException ( "Not enough data to read a pixel row" ) ;
453+ }
442454
443455 if ( ! this . hasAlpha )
444456 {
@@ -579,7 +591,7 @@ private void ReadRle<TPixel>(int width, int height, Buffer2D<TPixel> pixels, int
579591 where TPixel : unmanaged, IPixel < TPixel >
580592 {
581593 TPixel color = default ;
582- var alphaBits = this . tgaMetadata . AlphaChannelBits ;
594+ byte alphaBits = this . tgaMetadata . AlphaChannelBits ;
583595 using ( IMemoryOwner < byte > buffer = this . memoryAllocator . Allocate < byte > ( width * height * bytesPerPixel , AllocationOptions . Clean ) )
584596 {
585597 Span < byte > bufferSpan = buffer . GetSpan ( ) ;
@@ -624,8 +636,8 @@ private void ReadRle<TPixel>(int width, int height, Buffer2D<TPixel> pixels, int
624636 }
625637 else
626638 {
627- var alpha = alphaBits == 0 ? byte . MaxValue : bufferSpan [ idx + 3 ] ;
628- color . FromBgra32 ( new Bgra32 ( bufferSpan [ idx + 2 ] , bufferSpan [ idx + 1 ] , bufferSpan [ idx ] , ( byte ) alpha ) ) ;
639+ byte alpha = alphaBits == 0 ? byte . MaxValue : bufferSpan [ idx + 3 ] ;
640+ color . FromBgra32 ( new Bgra32 ( bufferSpan [ idx + 2 ] , bufferSpan [ idx + 1 ] , bufferSpan [ idx ] , alpha ) ) ;
629641 }
630642
631643 break ;
@@ -653,7 +665,12 @@ public IImageInfo Identify(BufferedReadStream stream, CancellationToken cancella
653665 private void ReadL8Row < TPixel > ( int width , Buffer2D < TPixel > pixels , Span < byte > row , int y )
654666 where TPixel : unmanaged, IPixel < TPixel >
655667 {
656- this . currentStream . Read ( row ) ;
668+ int bytesRead = this . currentStream . Read ( row ) ;
669+ if ( bytesRead != row . Length )
670+ {
671+ TgaThrowHelper . ThrowInvalidImageContentException ( "Not enough data to read a pixel row" ) ;
672+ }
673+
657674 Span < TPixel > pixelSpan = pixels . DangerousGetRowSpan ( y ) ;
658675 PixelOperations < TPixel > . Instance . FromL8Bytes ( this . Configuration , row , pixelSpan , width ) ;
659676 }
@@ -662,7 +679,7 @@ private void ReadL8Row<TPixel>(int width, Buffer2D<TPixel> pixels, Span<byte> ro
662679 private void ReadL8Pixel < TPixel > ( TPixel color , int x , Span < TPixel > pixelSpan )
663680 where TPixel : unmanaged, IPixel < TPixel >
664681 {
665- var pixelValue = ( byte ) this . currentStream . ReadByte ( ) ;
682+ byte pixelValue = ( byte ) this . currentStream . ReadByte ( ) ;
666683 color . FromL8 ( Unsafe . As < byte , L8 > ( ref pixelValue ) ) ;
667684 pixelSpan [ x ] = color ;
668685 }
@@ -671,7 +688,12 @@ private void ReadL8Pixel<TPixel>(TPixel color, int x, Span<TPixel> pixelSpan)
671688 private void ReadBgr24Pixel < TPixel > ( TPixel color , int x , Span < TPixel > pixelSpan )
672689 where TPixel : unmanaged, IPixel < TPixel >
673690 {
674- this . currentStream . Read ( this . scratchBuffer , 0 , 3 ) ;
691+ int bytesRead = this . currentStream . Read ( this . scratchBuffer , 0 , 3 ) ;
692+ if ( bytesRead != 3 )
693+ {
694+ TgaThrowHelper . ThrowInvalidImageContentException ( "Not enough data to read a bgr pixel" ) ;
695+ }
696+
675697 color . FromBgr24 ( Unsafe . As < byte , Bgr24 > ( ref this . scratchBuffer [ 0 ] ) ) ;
676698 pixelSpan [ x ] = color ;
677699 }
@@ -680,7 +702,12 @@ private void ReadBgr24Pixel<TPixel>(TPixel color, int x, Span<TPixel> pixelSpan)
680702 private void ReadBgr24Row < TPixel > ( int width , Buffer2D < TPixel > pixels , Span < byte > row , int y )
681703 where TPixel : unmanaged, IPixel < TPixel >
682704 {
683- this . currentStream . Read ( row ) ;
705+ int bytesRead = this . currentStream . Read ( row ) ;
706+ if ( bytesRead != row . Length )
707+ {
708+ TgaThrowHelper . ThrowInvalidImageContentException ( "Not enough data to read a pixel row" ) ;
709+ }
710+
684711 Span < TPixel > pixelSpan = pixels . DangerousGetRowSpan ( y ) ;
685712 PixelOperations < TPixel > . Instance . FromBgr24Bytes ( this . Configuration , row , pixelSpan , width ) ;
686713 }
@@ -689,8 +716,13 @@ private void ReadBgr24Row<TPixel>(int width, Buffer2D<TPixel> pixels, Span<byte>
689716 private void ReadBgra32Pixel < TPixel > ( int x , TPixel color , Span < TPixel > pixelRow )
690717 where TPixel : unmanaged, IPixel < TPixel >
691718 {
692- this . currentStream . Read ( this . scratchBuffer , 0 , 4 ) ;
693- var alpha = this . tgaMetadata . AlphaChannelBits == 0 ? byte . MaxValue : this . scratchBuffer [ 3 ] ;
719+ int bytesRead = this . currentStream . Read ( this . scratchBuffer , 0 , 4 ) ;
720+ if ( bytesRead != 4 )
721+ {
722+ TgaThrowHelper . ThrowInvalidImageContentException ( "Not enough data to read a bgra pixel" ) ;
723+ }
724+
725+ byte alpha = this . tgaMetadata . AlphaChannelBits == 0 ? byte . MaxValue : this . scratchBuffer [ 3 ] ;
694726 color . FromBgra32 ( new Bgra32 ( this . scratchBuffer [ 2 ] , this . scratchBuffer [ 1 ] , this . scratchBuffer [ 0 ] , alpha ) ) ;
695727 pixelRow [ x ] = color ;
696728 }
@@ -699,7 +731,12 @@ private void ReadBgra32Pixel<TPixel>(int x, TPixel color, Span<TPixel> pixelRow)
699731 private void ReadBgra32Row < TPixel > ( int width , Buffer2D < TPixel > pixels , Span < byte > row , int y )
700732 where TPixel : unmanaged, IPixel < TPixel >
701733 {
702- this . currentStream . Read ( row ) ;
734+ int bytesRead = this . currentStream . Read ( row ) ;
735+ if ( bytesRead != row . Length )
736+ {
737+ TgaThrowHelper . ThrowInvalidImageContentException ( "Not enough data to read a pixel row" ) ;
738+ }
739+
703740 Span < TPixel > pixelSpan = pixels . DangerousGetRowSpan ( y ) ;
704741 PixelOperations < TPixel > . Instance . FromBgra32Bytes ( this . Configuration , row , pixelSpan , width ) ;
705742 }
@@ -709,6 +746,11 @@ private void ReadPalettedBgra16Pixel<TPixel>(Span<byte> palette, int colorMapPix
709746 where TPixel : unmanaged, IPixel < TPixel >
710747 {
711748 int colorIndex = this . currentStream . ReadByte ( ) ;
749+ if ( colorIndex == - 1 )
750+ {
751+ TgaThrowHelper . ThrowInvalidImageContentException ( "Not enough data to read color index" ) ;
752+ }
753+
712754 this . ReadPalettedBgra16Pixel ( palette , colorIndex , colorMapPixelSizeInBytes , ref color ) ;
713755 pixelRow [ x ] = color ;
714756 }
@@ -734,6 +776,11 @@ private void ReadPalettedBgr24Pixel<TPixel>(Span<byte> palette, int colorMapPixe
734776 where TPixel : unmanaged, IPixel < TPixel >
735777 {
736778 int colorIndex = this . currentStream . ReadByte ( ) ;
779+ if ( colorIndex == - 1 )
780+ {
781+ TgaThrowHelper . ThrowInvalidImageContentException ( "Not enough data to read color index" ) ;
782+ }
783+
737784 color . FromBgr24 ( Unsafe . As < byte , Bgr24 > ( ref palette [ colorIndex * colorMapPixelSizeInBytes ] ) ) ;
738785 pixelRow [ x ] = color ;
739786 }
@@ -743,6 +790,11 @@ private void ReadPalettedBgra32Pixel<TPixel>(Span<byte> palette, int colorMapPix
743790 where TPixel : unmanaged, IPixel < TPixel >
744791 {
745792 int colorIndex = this . currentStream . ReadByte ( ) ;
793+ if ( colorIndex == - 1 )
794+ {
795+ TgaThrowHelper . ThrowInvalidImageContentException ( "Not enough data to read color index" ) ;
796+ }
797+
746798 color . FromBgra32 ( Unsafe . As < byte , Bgra32 > ( ref palette [ colorIndex * colorMapPixelSizeInBytes ] ) ) ;
747799 pixelRow [ x ] = color ;
748800 }
@@ -757,7 +809,7 @@ private void ReadPalettedBgra32Pixel<TPixel>(Span<byte> palette, int colorMapPix
757809 private void UncompressRle ( int width , int height , Span < byte > buffer , int bytesPerPixel )
758810 {
759811 int uncompressedPixels = 0 ;
760- var pixel = new byte [ bytesPerPixel ] ;
812+ Span < byte > pixel = this . scratchBuffer . AsSpan ( 0 , bytesPerPixel ) ;
761813 int totalPixels = width * height ;
762814 while ( uncompressedPixels < totalPixels )
763815 {
@@ -768,11 +820,16 @@ private void UncompressRle(int width, int height, Span<byte> buffer, int bytesPe
768820 if ( highBit == 1 )
769821 {
770822 int runLength = runLengthByte & 127 ;
771- this . currentStream . Read ( pixel , 0 , bytesPerPixel ) ;
823+ int bytesRead = this . currentStream . Read ( pixel , 0 , bytesPerPixel ) ;
824+ if ( bytesRead != bytesPerPixel )
825+ {
826+ TgaThrowHelper . ThrowInvalidImageContentException ( "Not enough data to read a pixel from the stream" ) ;
827+ }
828+
772829 int bufferIdx = uncompressedPixels * bytesPerPixel ;
773830 for ( int i = 0 ; i < runLength + 1 ; i ++ , uncompressedPixels ++ )
774831 {
775- pixel . AsSpan ( ) . CopyTo ( buffer . Slice ( bufferIdx ) ) ;
832+ pixel . CopyTo ( buffer . Slice ( bufferIdx ) ) ;
776833 bufferIdx += bytesPerPixel ;
777834 }
778835 }
@@ -783,8 +840,13 @@ private void UncompressRle(int width, int height, Span<byte> buffer, int bytesPe
783840 int bufferIdx = uncompressedPixels * bytesPerPixel ;
784841 for ( int i = 0 ; i < runLength + 1 ; i ++ , uncompressedPixels ++ )
785842 {
786- this . currentStream . Read ( pixel , 0 , bytesPerPixel ) ;
787- pixel . AsSpan ( ) . CopyTo ( buffer . Slice ( bufferIdx ) ) ;
843+ int bytesRead = this . currentStream . Read ( pixel , 0 , bytesPerPixel ) ;
844+ if ( bytesRead != bytesPerPixel )
845+ {
846+ TgaThrowHelper . ThrowInvalidImageContentException ( "Not enough data to read a pixel from the stream" ) ;
847+ }
848+
849+ pixel . CopyTo ( buffer . Slice ( bufferIdx ) ) ;
788850 bufferIdx += bytesPerPixel ;
789851 }
790852 }
@@ -815,17 +877,12 @@ private static int InvertY(int y, int height, TgaImageOrigin origin)
815877 /// <param name="origin">The image origin.</param>
816878 /// <returns>True, if y coordinate needs to be inverted.</returns>
817879 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
818- private static bool InvertY ( TgaImageOrigin origin )
880+ private static bool InvertY ( TgaImageOrigin origin ) => origin switch
819881 {
820- switch ( origin )
821- {
822- case TgaImageOrigin . BottomLeft :
823- case TgaImageOrigin . BottomRight :
824- return true ;
825- default :
826- return false ;
827- }
828- }
882+ TgaImageOrigin . BottomLeft => true ,
883+ TgaImageOrigin . BottomRight => true ,
884+ _ => false
885+ } ;
829886
830887 /// <summary>
831888 /// Returns the x- value based on the given width.
@@ -851,17 +908,13 @@ private static int InvertX(int x, int width, TgaImageOrigin origin)
851908 /// <param name="origin">The image origin.</param>
852909 /// <returns>True, if x coordinate needs to be inverted.</returns>
853910 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
854- private static bool InvertX ( TgaImageOrigin origin )
855- {
856- switch ( origin )
911+ private static bool InvertX ( TgaImageOrigin origin ) =>
912+ origin switch
857913 {
858- case TgaImageOrigin . TopRight :
859- case TgaImageOrigin . BottomRight :
860- return true ;
861- default :
862- return false ;
863- }
864- }
914+ TgaImageOrigin . TopRight => true ,
915+ TgaImageOrigin . BottomRight => true ,
916+ _ => false
917+ } ;
865918
866919 /// <summary>
867920 /// Reads the tga file header from the stream.
@@ -880,8 +933,8 @@ private TgaImageOrigin ReadFileHeader(BufferedReadStream stream)
880933 this . tgaMetadata = this . metadata . GetTgaMetadata ( ) ;
881934 this . tgaMetadata . BitsPerPixel = ( TgaBitsPerPixel ) this . fileHeader . PixelDepth ;
882935
883- var alphaBits = this . fileHeader . ImageDescriptor & 0xf ;
884- if ( alphaBits != 0 && alphaBits != 1 && alphaBits != 8 )
936+ int alphaBits = this . fileHeader . ImageDescriptor & 0xf ;
937+ if ( alphaBits is not 0 and not 1 and not 8 )
885938 {
886939 TgaThrowHelper . ThrowInvalidImageContentException ( "Invalid alpha channel bits" ) ;
887940 }
0 commit comments