Skip to content

Commit f4cc295

Browse files
Decode tile rows directly. Fix #2873
1 parent 313a7e8 commit f4cc295

File tree

1 file changed

+17
-18
lines changed

1 file changed

+17
-18
lines changed

src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -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,23 @@ private void DecodeTilesChunky<TPixel>(
666664
cancellationToken);
667665

668666
int tileBufferOffset = 0;
669-
uncompressedPixelBufferOffset += bytesPerTileRow * tileX;
670-
int bytesToCopy = isLastHorizontalTile ? RoundUpToMultipleOfEight(bitsPerPixel * remainingPixelsInRow) : bytesPerTileRow;
671-
for (int y = 0; y < tileLength; y++)
667+
for (int y = rowStartY; y < rowEndY; y++)
672668
{
673-
Span<byte> uncompressedPixelRow = uncompressedPixelBufferSpan.Slice(uncompressedPixelBufferOffset, bytesToCopy);
674-
tileBufferSpan.Slice(tileBufferOffset, bytesToCopy).CopyTo(uncompressedPixelRow);
669+
int bytesToCopy = isLastHorizontalTile ? RoundUpToMultipleOfEight(bitsPerPixel * remainingPixelsInRow) : bytesPerTileRow;
670+
ReadOnlySpan<byte> tileRowSpan = tileBufferSpan.Slice(tileBufferOffset, bytesToCopy);
671+
672+
// Decode the tile row directly into the pixel buffer.
673+
int left = tileX * tileWidth;
674+
int rowWidth = Math.Min(tileWidth, remainingPixelsInRow);
675+
676+
colorDecoder.Decode(tileRowSpan, pixels, left, y, rowWidth, 1);
677+
675678
tileBufferOffset += bytesPerTileRow;
676-
uncompressedPixelBufferOffset += bytesPerRow;
677679
}
678680

679-
remainingPixelsInRow -= tileWidth;
680681
tileIndex++;
681682
}
682683
}
683-
684-
colorDecoder.Decode(uncompressedPixelBufferSpan, pixels, 0, 0, width, height);
685684
}
686685

687686
private TiffBaseColorDecoder<TPixel> CreateChunkyColorDecoder<TPixel>()

0 commit comments

Comments
 (0)