@@ -453,6 +453,7 @@ private void ReadRle24<TPixel>(BufferedReadStream stream, Buffer2D<TPixel> pixel
453
453
/// <param name="rowsWithUndefinedPixels">Keeps track of rows, which have undefined pixels.</param>
454
454
private void UncompressRle4 ( BufferedReadStream stream , int w , Span < byte > buffer , Span < bool > undefinedPixels , Span < bool > rowsWithUndefinedPixels )
455
455
{
456
+ Span < byte > scratchBuffer = stackalloc byte [ 128 ] ;
456
457
Span < byte > cmd = stackalloc byte [ 2 ] ;
457
458
int count = 0 ;
458
459
@@ -491,9 +492,9 @@ private void UncompressRle4(BufferedReadStream stream, int w, Span<byte> buffer,
491
492
int max = cmd [ 1 ] ;
492
493
int bytesToRead = ( int ) ( ( ( uint ) max + 1 ) / 2 ) ;
493
494
494
- byte [ ] run = new byte [ bytesToRead ] ;
495
+ Span < byte > run = bytesToRead <= 128 ? scratchBuffer . Slice ( 0 , bytesToRead ) : new byte [ bytesToRead ] ;
495
496
496
- stream . Read ( run , 0 , run . Length ) ;
497
+ stream . Read ( run ) ;
497
498
498
499
int idx = 0 ;
499
500
for ( int i = 0 ; i < max ; i ++ )
@@ -559,6 +560,7 @@ private void UncompressRle4(BufferedReadStream stream, int w, Span<byte> buffer,
559
560
/// <param name="rowsWithUndefinedPixels">Keeps track of rows, which have undefined pixels.</param>
560
561
private void UncompressRle8 ( BufferedReadStream stream , int w , Span < byte > buffer , Span < bool > undefinedPixels , Span < bool > rowsWithUndefinedPixels )
561
562
{
563
+ Span < byte > scratchBuffer = stackalloc byte [ 128 ] ;
562
564
Span < byte > cmd = stackalloc byte [ 2 ] ;
563
565
int count = 0 ;
564
566
@@ -596,13 +598,13 @@ private void UncompressRle8(BufferedReadStream stream, int w, Span<byte> buffer,
596
598
// Take this number of bytes from the stream as uncompressed data.
597
599
int length = cmd [ 1 ] ;
598
600
599
- byte [ ] run = new byte [ length ] ;
601
+ Span < byte > run = length <= 128 ? scratchBuffer . Slice ( 0 , length ) : new byte [ length ] ;
600
602
601
- stream . Read ( run , 0 , run . Length ) ;
603
+ stream . Read ( run ) ;
602
604
603
- run . AsSpan ( ) . CopyTo ( buffer [ count ..] ) ;
605
+ run . CopyTo ( buffer [ count ..] ) ;
604
606
605
- count += run . Length ;
607
+ count += length ;
606
608
607
609
// Absolute mode data is aligned to two-byte word-boundary.
608
610
int padding = length & 1 ;
@@ -639,6 +641,7 @@ private void UncompressRle8(BufferedReadStream stream, int w, Span<byte> buffer,
639
641
/// <param name="rowsWithUndefinedPixels">Keeps track of rows, which have undefined pixels.</param>
640
642
private void UncompressRle24 ( BufferedReadStream stream , int w , Span < byte > buffer , Span < bool > undefinedPixels , Span < bool > rowsWithUndefinedPixels )
641
643
{
644
+ Span < byte > scratchBuffer = stackalloc byte [ 128 ] ;
642
645
Span < byte > cmd = stackalloc byte [ 2 ] ;
643
646
int uncompressedPixels = 0 ;
644
647
@@ -675,17 +678,18 @@ private void UncompressRle24(BufferedReadStream stream, int w, Span<byte> buffer
675
678
// If the second byte > 2, we are in 'absolute mode'.
676
679
// Take this number of bytes from the stream as uncompressed data.
677
680
int length = cmd [ 1 ] ;
681
+ int length3 = length * 3 ;
678
682
679
- byte [ ] run = new byte [ length * 3 ] ;
683
+ Span < byte > run = length3 <= 128 ? scratchBuffer . Slice ( 0 , length3 ) : new byte [ length3 ] ;
680
684
681
- stream . Read ( run , 0 , run . Length ) ;
685
+ stream . Read ( run ) ;
682
686
683
- run . AsSpan ( ) . CopyTo ( buffer [ ( uncompressedPixels * 3 ) ..] ) ;
687
+ run . CopyTo ( buffer [ ( uncompressedPixels * 3 ) ..] ) ;
684
688
685
689
uncompressedPixels += length ;
686
690
687
691
// Absolute mode data is aligned to two-byte word-boundary.
688
- int padding = run . Length & 1 ;
692
+ int padding = length3 & 1 ;
689
693
690
694
stream . Skip ( padding ) ;
691
695
@@ -1286,18 +1290,18 @@ private void ReadInfoHeader(BufferedReadStream stream)
1286
1290
// color masks for each color channel follow the info header.
1287
1291
if ( this . infoHeader . Compression == BmpCompression . BitFields )
1288
1292
{
1289
- byte [ ] bitfieldsBuffer = new byte [ 12 ] ;
1290
- stream . Read ( bitfieldsBuffer , 0 , 12 ) ;
1291
- Span < byte > data = bitfieldsBuffer . AsSpan ( ) ;
1293
+ Span < byte > bitfieldsBuffer = stackalloc byte [ 12 ] ;
1294
+ stream . Read ( bitfieldsBuffer ) ;
1295
+ Span < byte > data = bitfieldsBuffer ;
1292
1296
this . infoHeader . RedMask = BinaryPrimitives . ReadInt32LittleEndian ( data [ ..4 ] ) ;
1293
1297
this . infoHeader . GreenMask = BinaryPrimitives . ReadInt32LittleEndian ( data . Slice ( 4 , 4 ) ) ;
1294
1298
this . infoHeader . BlueMask = BinaryPrimitives . ReadInt32LittleEndian ( data . Slice ( 8 , 4 ) ) ;
1295
1299
}
1296
1300
else if ( this . infoHeader . Compression == BmpCompression . BI_ALPHABITFIELDS )
1297
1301
{
1298
- byte [ ] bitfieldsBuffer = new byte [ 16 ] ;
1299
- stream . Read ( bitfieldsBuffer , 0 , 16 ) ;
1300
- Span < byte > data = bitfieldsBuffer . AsSpan ( ) ;
1302
+ Span < byte > bitfieldsBuffer = stackalloc byte [ 16 ] ;
1303
+ stream . Read ( bitfieldsBuffer ) ;
1304
+ Span < byte > data = bitfieldsBuffer ;
1301
1305
this . infoHeader . RedMask = BinaryPrimitives . ReadInt32LittleEndian ( data [ ..4 ] ) ;
1302
1306
this . infoHeader . GreenMask = BinaryPrimitives . ReadInt32LittleEndian ( data . Slice ( 4 , 4 ) ) ;
1303
1307
this . infoHeader . BlueMask = BinaryPrimitives . ReadInt32LittleEndian ( data . Slice ( 8 , 4 ) ) ;
@@ -1470,7 +1474,7 @@ private int ReadImageHeaders(BufferedReadStream stream, out bool inverted, out b
1470
1474
{
1471
1475
// Usually the color palette is 1024 byte (256 colors * 4), but the documentation does not mention a size limit.
1472
1476
// Make sure, that we will not read pass the bitmap offset (starting position of image data).
1473
- if ( ( stream . Position + colorMapSizeBytes ) > this . fileHeader . Offset )
1477
+ if ( stream . Position > this . fileHeader . Offset - colorMapSizeBytes )
1474
1478
{
1475
1479
BmpThrowHelper . ThrowInvalidImageContentException (
1476
1480
$ "Reading the color map would read beyond the bitmap offset. Either the color map size of '{ colorMapSizeBytes } ' is invalid or the bitmap offset.") ;
0 commit comments