@@ -648,7 +648,7 @@ private void DecodeTilesPlanar<TPixel>(
648648 }
649649
650650 /// <summary>
651- /// Decodes the image data for Tiff's which arrange the pixel data in tiles and the chunky configuration.
651+ /// Decodes the image data for TIFFs which arrange the pixel data in tiles and the chunky configuration.
652652 /// </summary>
653653 /// <typeparam name="TPixel">The pixel format.</typeparam>
654654 /// <param name="frame">The image frame to decode into.</param>
@@ -674,28 +674,26 @@ private void DecodeTilesChunky<TPixel>(
674674 int width = pixels . Width ;
675675 int height = pixels . Height ;
676676 int bitsPerPixel = this . BitsPerPixel ;
677-
678- int bytesPerRow = RoundUpToMultipleOfEight ( width * bitsPerPixel ) ;
679677 int bytesPerTileRow = RoundUpToMultipleOfEight ( tileWidth * bitsPerPixel ) ;
680- int uncompressedTilesSize = bytesPerTileRow * tileLength ;
681- using IMemoryOwner < byte > tileBuffer = this . memoryAllocator . Allocate < byte > ( uncompressedTilesSize , AllocationOptions . Clean ) ;
682- using IMemoryOwner < byte > uncompressedPixelBuffer = this . memoryAllocator . Allocate < byte > ( tilesDown * tileLength * bytesPerRow , AllocationOptions . Clean ) ;
678+
679+ using IMemoryOwner < byte > tileBuffer = this . memoryAllocator . Allocate < byte > ( bytesPerTileRow * tileLength , AllocationOptions . Clean ) ;
683680 Span < byte > tileBufferSpan = tileBuffer . GetSpan ( ) ;
684- Span < byte > uncompressedPixelBufferSpan = uncompressedPixelBuffer . GetSpan ( ) ;
685681
686682 using TiffBaseDecompressor decompressor = this . CreateDecompressor < TPixel > ( frame . Width , bitsPerPixel ) ;
687683 TiffBaseColorDecoder < TPixel > colorDecoder = this . CreateChunkyColorDecoder < TPixel > ( ) ;
688684
689685 int tileIndex = 0 ;
690686 for ( int tileY = 0 ; tileY < tilesDown ; tileY ++ )
691687 {
692- int remainingPixelsInRow = width ;
688+ int rowStartY = tileY * tileLength ;
689+ int rowEndY = Math . Min ( rowStartY + tileLength , height ) ;
690+
693691 for ( int tileX = 0 ; tileX < tilesAcross ; tileX ++ )
694692 {
695693 cancellationToken . ThrowIfCancellationRequested ( ) ;
696694
697- int uncompressedPixelBufferOffset = tileY * tileLength * bytesPerRow ;
698695 bool isLastHorizontalTile = tileX == tilesAcross - 1 ;
696+ int remainingPixelsInRow = width - ( tileX * tileWidth ) ;
699697
700698 decompressor . Decompress (
701699 this . inputStream ,
@@ -706,22 +704,21 @@ private void DecodeTilesChunky<TPixel>(
706704 cancellationToken ) ;
707705
708706 int tileBufferOffset = 0 ;
709- uncompressedPixelBufferOffset += bytesPerTileRow * tileX ;
710707 int bytesToCopy = isLastHorizontalTile ? RoundUpToMultipleOfEight ( bitsPerPixel * remainingPixelsInRow ) : bytesPerTileRow ;
711- for ( int y = 0 ; y < tileLength ; y ++ )
708+ int rowWidth = Math . Min ( tileWidth , remainingPixelsInRow ) ;
709+ int left = tileX * tileWidth ;
710+
711+ for ( int y = rowStartY ; y < rowEndY ; y ++ )
712712 {
713- Span < byte > uncompressedPixelRow = uncompressedPixelBufferSpan . Slice ( uncompressedPixelBufferOffset , bytesToCopy ) ;
714- tileBufferSpan . Slice ( tileBufferOffset , bytesToCopy ) . CopyTo ( uncompressedPixelRow ) ;
713+ // Decode the tile row directly into the pixel buffer.
714+ ReadOnlySpan < byte > tileRowSpan = tileBufferSpan . Slice ( tileBufferOffset , bytesToCopy ) ;
715+ colorDecoder . Decode ( tileRowSpan , pixels , left , y , rowWidth , 1 ) ;
715716 tileBufferOffset += bytesPerTileRow ;
716- uncompressedPixelBufferOffset += bytesPerRow ;
717717 }
718718
719- remainingPixelsInRow -= tileWidth ;
720719 tileIndex ++ ;
721720 }
722721 }
723-
724- colorDecoder . Decode ( uncompressedPixelBufferSpan , pixels , 0 , 0 , width , height ) ;
725722 }
726723
727724 private TiffBaseColorDecoder < TPixel > CreateChunkyColorDecoder < TPixel > ( )
0 commit comments