Skip to content

Commit 9c9cc0d

Browse files
Merge pull request #2879 from SixLabors/js/v4-chunk-tiff-allocation
V4 : Decode Chunky Tile Rows Directly.
2 parents 1d096b2 + 261fab1 commit 9c9cc0d

File tree

2 files changed

+15
-18
lines changed

2 files changed

+15
-18
lines changed

src/ImageSharp/Formats/Png/PngThrowHelper.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public static void ThrowInvalidParameter(object value, string message, [CallerAr
4444
=> throw new NotSupportedException($"Invalid {name}. {message}. Was '{value}'.");
4545

4646
[DoesNotReturn]
47-
public static void ThrowInvalidParameter(object value1, object value2, string message, [CallerArgumentExpression(nameof(value1))] string name1 = "", [CallerArgumentExpression(nameof(value1))] string name2 = "")
47+
public static void ThrowInvalidParameter(object value1, object value2, string message, [CallerArgumentExpression(nameof(value1))] string name1 = "", [CallerArgumentExpression(nameof(value2))] string name2 = "")
4848
=> throw new NotSupportedException($"Invalid {name1} or {name2}. {message}. Was '{value1}' and '{value2}'.");
4949

5050
[DoesNotReturn]

src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs

+14-17
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)