@@ -608,7 +608,7 @@ private void DecodeTilesPlanar<TPixel>(
608608 }
609609
610610 /// <summary>
611- /// Decodes the image data for Tiff's which arrange the pixel data in tiles and the chunky configuration.
611+ /// Decodes the image data for TIFFs which arrange the pixel data in tiles and the chunky configuration.
612612 /// </summary>
613613 /// <typeparam name="TPixel">The pixel format.</typeparam>
614614 /// <param name="frame">The image frame to decode into.</param>
@@ -634,28 +634,26 @@ private void DecodeTilesChunky<TPixel>(
634634 int width = pixels . Width ;
635635 int height = pixels . Height ;
636636 int bitsPerPixel = this . BitsPerPixel ;
637-
638- int bytesPerRow = RoundUpToMultipleOfEight ( width * bitsPerPixel ) ;
639637 int bytesPerTileRow = RoundUpToMultipleOfEight ( tileWidth * bitsPerPixel ) ;
640- int uncompressedTilesSize = bytesPerTileRow * tileLength ;
641- using IMemoryOwner < byte > tileBuffer = this . memoryAllocator . Allocate < byte > ( uncompressedTilesSize , AllocationOptions . Clean ) ;
642- using IMemoryOwner < byte > uncompressedPixelBuffer = this . memoryAllocator . Allocate < byte > ( tilesDown * tileLength * bytesPerRow , AllocationOptions . Clean ) ;
638+
639+ using IMemoryOwner < byte > tileBuffer = this . memoryAllocator . Allocate < byte > ( bytesPerTileRow * tileLength , AllocationOptions . Clean ) ;
643640 Span < byte > tileBufferSpan = tileBuffer . GetSpan ( ) ;
644- Span < byte > uncompressedPixelBufferSpan = uncompressedPixelBuffer . GetSpan ( ) ;
645641
646642 using TiffBaseDecompressor decompressor = this . CreateDecompressor < TPixel > ( frame . Width , bitsPerPixel ) ;
647643 TiffBaseColorDecoder < TPixel > colorDecoder = this . CreateChunkyColorDecoder < TPixel > ( ) ;
648644
649645 int tileIndex = 0 ;
650646 for ( int tileY = 0 ; tileY < tilesDown ; tileY ++ )
651647 {
652- int remainingPixelsInRow = width ;
648+ int rowStartY = tileY * tileLength ;
649+ int rowEndY = Math . Min ( rowStartY + tileLength , height ) ;
650+
653651 for ( int tileX = 0 ; tileX < tilesAcross ; tileX ++ )
654652 {
655653 cancellationToken . ThrowIfCancellationRequested ( ) ;
656654
657- int uncompressedPixelBufferOffset = tileY * tileLength * bytesPerRow ;
658655 bool isLastHorizontalTile = tileX == tilesAcross - 1 ;
656+ int remainingPixelsInRow = width - ( tileX * tileWidth ) ;
659657
660658 decompressor . Decompress (
661659 this . inputStream ,
@@ -666,22 +664,21 @@ private void DecodeTilesChunky<TPixel>(
666664 cancellationToken ) ;
667665
668666 int tileBufferOffset = 0 ;
669- uncompressedPixelBufferOffset += bytesPerTileRow * tileX ;
670667 int bytesToCopy = isLastHorizontalTile ? RoundUpToMultipleOfEight ( bitsPerPixel * remainingPixelsInRow ) : bytesPerTileRow ;
671- for ( int y = 0 ; y < tileLength ; y ++ )
668+ int rowWidth = Math . Min ( tileWidth , remainingPixelsInRow ) ;
669+ int left = tileX * tileWidth ;
670+
671+ for ( int y = rowStartY ; y < rowEndY ; y ++ )
672672 {
673- Span < byte > uncompressedPixelRow = uncompressedPixelBufferSpan . Slice ( uncompressedPixelBufferOffset , bytesToCopy ) ;
674- tileBufferSpan . Slice ( tileBufferOffset , bytesToCopy ) . CopyTo ( uncompressedPixelRow ) ;
673+ // Decode the tile row directly into the pixel buffer.
674+ ReadOnlySpan < byte > tileRowSpan = tileBufferSpan . Slice ( tileBufferOffset , bytesToCopy ) ;
675+ colorDecoder . Decode ( tileRowSpan , pixels , left , y , rowWidth , 1 ) ;
675676 tileBufferOffset += bytesPerTileRow ;
676- uncompressedPixelBufferOffset += bytesPerRow ;
677677 }
678678
679- remainingPixelsInRow -= tileWidth ;
680679 tileIndex ++ ;
681680 }
682681 }
683-
684- colorDecoder . Decode ( uncompressedPixelBufferSpan , pixels , 0 , 0 , width , height ) ;
685682 }
686683
687684 private TiffBaseColorDecoder < TPixel > CreateChunkyColorDecoder < TPixel > ( )
0 commit comments