@@ -423,27 +423,22 @@ private void ReadFrame<TPixel>(BufferedReadStream stream, ref Image<TPixel>? ima
423
423
424
424
// Determine the color table for this frame. If there is a local one, use it otherwise use the global color table.
425
425
bool hasLocalColorTable = this . imageDescriptor . LocalColorTableFlag ;
426
-
426
+ Span < byte > rawColorTable = default ;
427
427
if ( hasLocalColorTable )
428
428
{
429
429
// Read and store the local color table. We allocate the maximum possible size and slice to match.
430
430
int length = this . currentLocalColorTableSize = this . imageDescriptor . LocalColorTableSize * 3 ;
431
431
this . currentLocalColorTable ??= this . configuration . MemoryAllocator . Allocate < byte > ( 768 , AllocationOptions . Clean ) ;
432
432
stream . Read ( this . currentLocalColorTable . GetSpan ( ) [ ..length ] ) ;
433
- }
434
-
435
- Span < byte > rawColorTable = default ;
436
- if ( hasLocalColorTable )
437
- {
438
- rawColorTable = this . currentLocalColorTable ! . GetSpan ( ) [ ..this . currentLocalColorTableSize ] ;
433
+ rawColorTable = this . currentLocalColorTable ! . GetSpan ( ) [ ..length ] ;
439
434
}
440
435
else if ( this . globalColorTable != null )
441
436
{
442
437
rawColorTable = this . globalColorTable . GetSpan ( ) ;
443
438
}
444
439
445
440
ReadOnlySpan < Rgb24 > colorTable = MemoryMarshal . Cast < byte , Rgb24 > ( rawColorTable ) ;
446
- this . ReadFrameColors ( stream , ref image , ref previousFrame , colorTable , this . imageDescriptor ) ;
441
+ this . ReadFrameColors ( stream , ref image , ref previousFrame , colorTable ) ;
447
442
448
443
// Skip any remaining blocks
449
444
SkipBlock ( stream ) ;
@@ -457,15 +452,14 @@ private void ReadFrame<TPixel>(BufferedReadStream stream, ref Image<TPixel>? ima
457
452
/// <param name="image">The image to decode the information to.</param>
458
453
/// <param name="previousFrame">The previous frame.</param>
459
454
/// <param name="colorTable">The color table containing the available colors.</param>
460
- /// <param name="descriptor">The <see cref="GifImageDescriptor"/></param>
461
455
private void ReadFrameColors < TPixel > (
462
456
BufferedReadStream stream ,
463
457
ref Image < TPixel > ? image ,
464
458
ref ImageFrame < TPixel > ? previousFrame ,
465
- ReadOnlySpan < Rgb24 > colorTable ,
466
- in GifImageDescriptor descriptor )
459
+ ReadOnlySpan < Rgb24 > colorTable )
467
460
where TPixel : unmanaged, IPixel < TPixel >
468
461
{
462
+ GifImageDescriptor descriptor = this . imageDescriptor ;
469
463
int imageWidth = this . logicalScreenDescriptor . Width ;
470
464
int imageHeight = this . logicalScreenDescriptor . Height ;
471
465
bool transFlag = this . graphicsControlExtension . TransparencyFlag ;
@@ -528,7 +522,6 @@ private void ReadFrameColors<TPixel>(
528
522
// However we have images that exceed this that can be decoded by other libraries. #1530
529
523
using IMemoryOwner < byte > indicesRowOwner = this . memoryAllocator . Allocate < byte > ( descriptor . Width ) ;
530
524
Span < byte > indicesRow = indicesRowOwner . Memory . Span ;
531
- ref byte indicesRowRef = ref MemoryMarshal . GetReference ( indicesRow ) ;
532
525
533
526
int minCodeSize = stream . ReadByte ( ) ;
534
527
if ( LzwDecoder . IsValidMinCodeSize ( minCodeSize ) )
@@ -572,30 +565,36 @@ private void ReadFrameColors<TPixel>(
572
565
}
573
566
574
567
lzwDecoder . DecodePixelRow ( indicesRow ) ;
575
- ref TPixel rowRef = ref MemoryMarshal . GetReference ( imageFrame . PixelBuffer . DangerousGetRowSpan ( writeY ) ) ;
568
+
569
+ // #403 The left + width value can be larger than the image width
570
+ int maxX = Math . Min ( descriptorRight , imageWidth ) ;
571
+ Span < TPixel > row = imageFrame . PixelBuffer . DangerousGetRowSpan ( writeY ) ;
572
+
573
+ // Take the descriptorLeft..maxX slice of the row, so the loop can be simplified.
574
+ row = row [ descriptorLeft ..maxX ] ;
576
575
577
576
if ( ! transFlag )
578
577
{
579
- // #403 The left + width value can be larger than the image width
580
- for ( int x = descriptorLeft ; x < descriptorRight && x < imageWidth ; x ++ )
578
+ for ( int x = 0 ; x < row . Length ; x ++ )
581
579
{
582
- int index = Numerics . Clamp ( Unsafe . Add ( ref indicesRowRef , ( uint ) ( x - descriptorLeft ) ) , 0 , colorTableMaxIdx ) ;
583
- Unsafe . Add ( ref rowRef , ( uint ) x ) = TPixel. FromRgb24 ( colorTable [ index ] ) ;
580
+ int index = indicesRow [ x ] ;
581
+ index = Numerics . Clamp ( index , 0 , colorTableMaxIdx ) ;
582
+ row [ x ] = TPixel . FromRgb24 ( colorTable [ index ] ) ;
584
583
}
585
584
}
586
585
else
587
586
{
588
- for ( int x = descriptorLeft ; x < descriptorRight && x < imageWidth ; x ++ )
587
+ for ( int x = 0 ; x < row . Length ; x ++ )
589
588
{
590
- int index = Unsafe . Add ( ref indicesRowRef , ( uint ) ( x - descriptorLeft ) ) ;
589
+ int index = indicesRow [ x ] ;
591
590
592
591
// Treat any out of bounds values as transparent.
593
592
if ( index > colorTableMaxIdx || index == transIndex )
594
593
{
595
594
continue ;
596
595
}
597
596
598
- Unsafe . Add ( ref rowRef , ( uint ) x ) = TPixel. FromRgb24 ( colorTable [ index ] ) ;
597
+ row [ x ] = TPixel . FromRgb24 ( colorTable [ index ] ) ;
599
598
}
600
599
}
601
600
}
0 commit comments