@@ -423,27 +423,22 @@ private void ReadFrame<TPixel>(BufferedReadStream stream, ref Image<TPixel>? ima
423423
424424 // Determine the color table for this frame. If there is a local one, use it otherwise use the global color table.
425425 bool hasLocalColorTable = this . imageDescriptor . LocalColorTableFlag ;
426-
426+ Span < byte > rawColorTable = default ;
427427 if ( hasLocalColorTable )
428428 {
429429 // Read and store the local color table. We allocate the maximum possible size and slice to match.
430430 int length = this . currentLocalColorTableSize = this . imageDescriptor . LocalColorTableSize * 3 ;
431431 this . currentLocalColorTable ??= this . configuration . MemoryAllocator . Allocate < byte > ( 768 , AllocationOptions . Clean ) ;
432432 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 ] ;
439434 }
440435 else if ( this . globalColorTable != null )
441436 {
442437 rawColorTable = this . globalColorTable . GetSpan ( ) ;
443438 }
444439
445440 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 ) ;
447442
448443 // Skip any remaining blocks
449444 SkipBlock ( stream ) ;
@@ -457,15 +452,14 @@ private void ReadFrame<TPixel>(BufferedReadStream stream, ref Image<TPixel>? ima
457452 /// <param name="image">The image to decode the information to.</param>
458453 /// <param name="previousFrame">The previous frame.</param>
459454 /// <param name="colorTable">The color table containing the available colors.</param>
460- /// <param name="descriptor">The <see cref="GifImageDescriptor"/></param>
461455 private void ReadFrameColors < TPixel > (
462456 BufferedReadStream stream ,
463457 ref Image < TPixel > ? image ,
464458 ref ImageFrame < TPixel > ? previousFrame ,
465- ReadOnlySpan < Rgb24 > colorTable ,
466- in GifImageDescriptor descriptor )
459+ ReadOnlySpan < Rgb24 > colorTable )
467460 where TPixel : unmanaged, IPixel < TPixel >
468461 {
462+ GifImageDescriptor descriptor = this . imageDescriptor ;
469463 int imageWidth = this . logicalScreenDescriptor . Width ;
470464 int imageHeight = this . logicalScreenDescriptor . Height ;
471465 bool transFlag = this . graphicsControlExtension . TransparencyFlag ;
@@ -528,7 +522,6 @@ private void ReadFrameColors<TPixel>(
528522 // However we have images that exceed this that can be decoded by other libraries. #1530
529523 using IMemoryOwner < byte > indicesRowOwner = this . memoryAllocator . Allocate < byte > ( descriptor . Width ) ;
530524 Span < byte > indicesRow = indicesRowOwner . Memory . Span ;
531- ref byte indicesRowRef = ref MemoryMarshal . GetReference ( indicesRow ) ;
532525
533526 int minCodeSize = stream . ReadByte ( ) ;
534527 if ( LzwDecoder . IsValidMinCodeSize ( minCodeSize ) )
@@ -572,30 +565,36 @@ private void ReadFrameColors<TPixel>(
572565 }
573566
574567 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 ] ;
576575
577576 if ( ! transFlag )
578577 {
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 ++ )
581579 {
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 ] ) ;
584583 }
585584 }
586585 else
587586 {
588- for ( int x = descriptorLeft ; x < descriptorRight && x < imageWidth ; x ++ )
587+ for ( int x = 0 ; x < row . Length ; x ++ )
589588 {
590- int index = Unsafe . Add ( ref indicesRowRef , ( uint ) ( x - descriptorLeft ) ) ;
589+ int index = indicesRow [ x ] ;
591590
592591 // Treat any out of bounds values as transparent.
593592 if ( index > colorTableMaxIdx || index == transIndex )
594593 {
595594 continue ;
596595 }
597596
598- Unsafe . Add ( ref rowRef , ( uint ) x ) = TPixel. FromRgb24 ( colorTable [ index ] ) ;
597+ row [ x ] = TPixel . FromRgb24 ( colorTable [ index ] ) ;
599598 }
600599 }
601600 }
0 commit comments