@@ -17,11 +17,6 @@ namespace SixLabors.ImageSharp.Formats.Tga;
17
17
/// </summary>
18
18
internal sealed class TgaDecoderCore : IImageDecoderInternals
19
19
{
20
- /// <summary>
21
- /// A scratch buffer to reduce allocations.
22
- /// </summary>
23
- private readonly byte [ ] scratchBuffer = new byte [ 4 ] ;
24
-
25
20
/// <summary>
26
21
/// General configuration options.
27
22
/// </summary>
@@ -407,6 +402,7 @@ private void ReadBgra16<TPixel>(BufferedReadStream stream, int width, int height
407
402
bool invertX = InvertX ( origin ) ;
408
403
using IMemoryOwner < byte > row = this . memoryAllocator . AllocatePaddedPixelRowBuffer ( width , 2 , 0 ) ;
409
404
Span < byte > rowSpan = row . GetSpan ( ) ;
405
+ Span < byte > scratchBuffer = stackalloc byte [ 2 ] ;
410
406
411
407
for ( int y = 0 ; y < height ; y ++ )
412
408
{
@@ -417,24 +413,24 @@ private void ReadBgra16<TPixel>(BufferedReadStream stream, int width, int height
417
413
{
418
414
for ( int x = width - 1 ; x >= 0 ; x -- )
419
415
{
420
- int bytesRead = stream . Read ( this . scratchBuffer , 0 , 2 ) ;
416
+ int bytesRead = stream . Read ( scratchBuffer ) ;
421
417
if ( bytesRead != 2 )
422
418
{
423
419
TgaThrowHelper . ThrowInvalidImageContentException ( "Not enough data to read a pixel row" ) ;
424
420
}
425
421
426
422
if ( ! this . hasAlpha )
427
423
{
428
- this . scratchBuffer [ 1 ] |= 1 << 7 ;
424
+ scratchBuffer [ 1 ] |= 1 << 7 ;
429
425
}
430
426
431
427
if ( this . fileHeader . ImageType == TgaImageType . BlackAndWhite )
432
428
{
433
- color . FromLa16 ( Unsafe . As < byte , La16 > ( ref MemoryMarshal . GetArrayDataReference ( this . scratchBuffer ) ) ) ;
429
+ color . FromLa16 ( Unsafe . As < byte , La16 > ( ref MemoryMarshal . GetReference ( scratchBuffer ) ) ) ;
434
430
}
435
431
else
436
432
{
437
- color . FromBgra5551 ( Unsafe . As < byte , Bgra5551 > ( ref MemoryMarshal . GetArrayDataReference ( this . scratchBuffer ) ) ) ;
433
+ color . FromBgra5551 ( Unsafe . As < byte , Bgra5551 > ( ref MemoryMarshal . GetReference ( scratchBuffer ) ) ) ;
438
434
}
439
435
440
436
pixelSpan [ x ] = color ;
@@ -484,14 +480,15 @@ private void ReadBgr24<TPixel>(BufferedReadStream stream, int width, int height,
484
480
bool invertX = InvertX ( origin ) ;
485
481
if ( invertX )
486
482
{
483
+ Span < byte > scratchBuffer = stackalloc byte [ 4 ] ;
487
484
TPixel color = default ;
488
485
for ( int y = 0 ; y < height ; y ++ )
489
486
{
490
487
int newY = InvertY ( y , height , origin ) ;
491
488
Span < TPixel > pixelSpan = pixels . DangerousGetRowSpan ( newY ) ;
492
489
for ( int x = width - 1 ; x >= 0 ; x -- )
493
490
{
494
- this . ReadBgr24Pixel ( stream , color , x , pixelSpan ) ;
491
+ ReadBgr24Pixel ( stream , color , x , pixelSpan , scratchBuffer ) ;
495
492
}
496
493
}
497
494
@@ -558,6 +555,8 @@ private void ReadBgra32<TPixel>(BufferedReadStream stream, int width, int height
558
555
return ;
559
556
}
560
557
558
+ Span < byte > scratchBuffer = stackalloc byte [ 4 ] ;
559
+
561
560
for ( int y = 0 ; y < height ; y ++ )
562
561
{
563
562
int newY = InvertY ( y , height , origin ) ;
@@ -566,14 +565,14 @@ private void ReadBgra32<TPixel>(BufferedReadStream stream, int width, int height
566
565
{
567
566
for ( int x = width - 1 ; x >= 0 ; x -- )
568
567
{
569
- this . ReadBgra32Pixel ( stream , x , color , pixelRow ) ;
568
+ this . ReadBgra32Pixel ( stream , x , color , pixelRow , scratchBuffer ) ;
570
569
}
571
570
}
572
571
else
573
572
{
574
573
for ( int x = 0 ; x < width ; x ++ )
575
574
{
576
- this . ReadBgra32Pixel ( stream , x , color , pixelRow ) ;
575
+ this . ReadBgra32Pixel ( stream , x , color , pixelRow , scratchBuffer ) ;
577
576
}
578
577
}
579
578
}
@@ -687,16 +686,16 @@ private static void ReadL8Pixel<TPixel>(BufferedReadStream stream, TPixel color,
687
686
}
688
687
689
688
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
690
- private void ReadBgr24Pixel < TPixel > ( BufferedReadStream stream , TPixel color , int x , Span < TPixel > pixelSpan )
689
+ private static void ReadBgr24Pixel < TPixel > ( BufferedReadStream stream , TPixel color , int x , Span < TPixel > pixelSpan , Span < byte > scratchBuffer )
691
690
where TPixel : unmanaged, IPixel < TPixel >
692
691
{
693
- int bytesRead = stream . Read ( this . scratchBuffer , 0 , 3 ) ;
692
+ int bytesRead = stream . Read ( scratchBuffer , 0 , 3 ) ;
694
693
if ( bytesRead != 3 )
695
694
{
696
695
TgaThrowHelper . ThrowInvalidImageContentException ( "Not enough data to read a bgr pixel" ) ;
697
696
}
698
697
699
- color . FromBgr24 ( Unsafe . As < byte , Bgr24 > ( ref MemoryMarshal . GetArrayDataReference ( this . scratchBuffer ) ) ) ;
698
+ color . FromBgr24 ( Unsafe . As < byte , Bgr24 > ( ref MemoryMarshal . GetReference ( scratchBuffer ) ) ) ;
700
699
pixelSpan [ x ] = color ;
701
700
}
702
701
@@ -715,19 +714,19 @@ private void ReadBgr24Row<TPixel>(BufferedReadStream stream, int width, Buffer2D
715
714
}
716
715
717
716
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
718
- private void ReadBgra32Pixel < TPixel > ( BufferedReadStream stream , int x , TPixel color , Span < TPixel > pixelRow )
717
+ private void ReadBgra32Pixel < TPixel > ( BufferedReadStream stream , int x , TPixel color , Span < TPixel > pixelRow , Span < byte > scratchBuffer )
719
718
where TPixel : unmanaged, IPixel < TPixel >
720
719
{
721
- int bytesRead = stream . Read ( this . scratchBuffer , 0 , 4 ) ;
720
+ int bytesRead = stream . Read ( scratchBuffer , 0 , 4 ) ;
722
721
if ( bytesRead != 4 )
723
722
{
724
723
TgaThrowHelper . ThrowInvalidImageContentException ( "Not enough data to read a bgra pixel" ) ;
725
724
}
726
725
727
726
Guard . NotNull ( this . tgaMetadata ) ;
728
727
729
- byte alpha = this . tgaMetadata . AlphaChannelBits == 0 ? byte . MaxValue : this . scratchBuffer [ 3 ] ;
730
- color . FromBgra32 ( new Bgra32 ( this . scratchBuffer [ 2 ] , this . scratchBuffer [ 1 ] , this . scratchBuffer [ 0 ] , alpha ) ) ;
728
+ byte alpha = this . tgaMetadata . AlphaChannelBits == 0 ? byte . MaxValue : scratchBuffer [ 3 ] ;
729
+ color . FromBgra32 ( new Bgra32 ( scratchBuffer [ 2 ] , scratchBuffer [ 1 ] , scratchBuffer [ 0 ] , alpha ) ) ;
731
730
pixelRow [ x ] = color ;
732
731
}
733
732
@@ -814,7 +813,7 @@ private static void ReadPalettedBgra32Pixel<TPixel>(BufferedReadStream stream, S
814
813
private void UncompressRle ( BufferedReadStream stream , int width , int height , Span < byte > buffer , int bytesPerPixel )
815
814
{
816
815
int uncompressedPixels = 0 ;
817
- Span < byte > pixel = this . scratchBuffer . AsSpan ( 0 , bytesPerPixel ) ;
816
+ Span < byte > pixel = stackalloc byte [ bytesPerPixel ] ;
818
817
int totalPixels = width * height ;
819
818
while ( uncompressedPixels < totalPixels )
820
819
{
@@ -825,7 +824,7 @@ private void UncompressRle(BufferedReadStream stream, int width, int height, Spa
825
824
if ( highBit == 1 )
826
825
{
827
826
int runLength = runLengthByte & 127 ;
828
- int bytesRead = stream . Read ( pixel , 0 , bytesPerPixel ) ;
827
+ int bytesRead = stream . Read ( pixel ) ;
829
828
if ( bytesRead != bytesPerPixel )
830
829
{
831
830
TgaThrowHelper . ThrowInvalidImageContentException ( "Not enough data to read a pixel from the stream" ) ;
@@ -845,7 +844,7 @@ private void UncompressRle(BufferedReadStream stream, int width, int height, Spa
845
844
int bufferIdx = uncompressedPixels * bytesPerPixel ;
846
845
for ( int i = 0 ; i < runLength + 1 ; i ++ , uncompressedPixels ++ )
847
846
{
848
- int bytesRead = stream . Read ( pixel , 0 , bytesPerPixel ) ;
847
+ int bytesRead = stream . Read ( pixel ) ;
849
848
if ( bytesRead != bytesPerPixel )
850
849
{
851
850
TgaThrowHelper . ThrowInvalidImageContentException ( "Not enough data to read a pixel from the stream" ) ;
0 commit comments