Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V4 : Decode Chunky Tile Rows Directly. #2879

Merged
merged 1 commit into from
Feb 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/ImageSharp/Formats/Png/PngThrowHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public static void ThrowInvalidParameter(object value, string message, [CallerAr
=> throw new NotSupportedException($"Invalid {name}. {message}. Was '{value}'.");

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

[DoesNotReturn]
Expand Down
31 changes: 14 additions & 17 deletions src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -648,7 +648,7 @@ private void DecodeTilesPlanar<TPixel>(
}

/// <summary>
/// Decodes the image data for Tiff's which arrange the pixel data in tiles and the chunky configuration.
/// Decodes the image data for TIFFs which arrange the pixel data in tiles and the chunky configuration.
Copy link
Preview

Copilot AI Feb 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected spelling of 'Tiff's' to 'TIFFs'.

Copilot is powered by AI, so mistakes are possible. Review output carefully before use.

Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to disable copilot? I dont think this is helpful.

/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="frame">The image frame to decode into.</param>
Expand All @@ -674,28 +674,26 @@ private void DecodeTilesChunky<TPixel>(
int width = pixels.Width;
int height = pixels.Height;
int bitsPerPixel = this.BitsPerPixel;

int bytesPerRow = RoundUpToMultipleOfEight(width * bitsPerPixel);
int bytesPerTileRow = RoundUpToMultipleOfEight(tileWidth * bitsPerPixel);
int uncompressedTilesSize = bytesPerTileRow * tileLength;
using IMemoryOwner<byte> tileBuffer = this.memoryAllocator.Allocate<byte>(uncompressedTilesSize, AllocationOptions.Clean);
using IMemoryOwner<byte> uncompressedPixelBuffer = this.memoryAllocator.Allocate<byte>(tilesDown * tileLength * bytesPerRow, AllocationOptions.Clean);

using IMemoryOwner<byte> tileBuffer = this.memoryAllocator.Allocate<byte>(bytesPerTileRow * tileLength, AllocationOptions.Clean);
Span<byte> tileBufferSpan = tileBuffer.GetSpan();
Span<byte> uncompressedPixelBufferSpan = uncompressedPixelBuffer.GetSpan();

using TiffBaseDecompressor decompressor = this.CreateDecompressor<TPixel>(frame.Width, bitsPerPixel);
TiffBaseColorDecoder<TPixel> colorDecoder = this.CreateChunkyColorDecoder<TPixel>();

int tileIndex = 0;
for (int tileY = 0; tileY < tilesDown; tileY++)
{
int remainingPixelsInRow = width;
int rowStartY = tileY * tileLength;
int rowEndY = Math.Min(rowStartY + tileLength, height);

for (int tileX = 0; tileX < tilesAcross; tileX++)
{
cancellationToken.ThrowIfCancellationRequested();

int uncompressedPixelBufferOffset = tileY * tileLength * bytesPerRow;
bool isLastHorizontalTile = tileX == tilesAcross - 1;
int remainingPixelsInRow = width - (tileX * tileWidth);

decompressor.Decompress(
this.inputStream,
Expand All @@ -706,22 +704,21 @@ private void DecodeTilesChunky<TPixel>(
cancellationToken);

int tileBufferOffset = 0;
uncompressedPixelBufferOffset += bytesPerTileRow * tileX;
int bytesToCopy = isLastHorizontalTile ? RoundUpToMultipleOfEight(bitsPerPixel * remainingPixelsInRow) : bytesPerTileRow;
for (int y = 0; y < tileLength; y++)
int rowWidth = Math.Min(tileWidth, remainingPixelsInRow);
int left = tileX * tileWidth;

for (int y = rowStartY; y < rowEndY; y++)
{
Span<byte> uncompressedPixelRow = uncompressedPixelBufferSpan.Slice(uncompressedPixelBufferOffset, bytesToCopy);
tileBufferSpan.Slice(tileBufferOffset, bytesToCopy).CopyTo(uncompressedPixelRow);
// Decode the tile row directly into the pixel buffer.
ReadOnlySpan<byte> tileRowSpan = tileBufferSpan.Slice(tileBufferOffset, bytesToCopy);
colorDecoder.Decode(tileRowSpan, pixels, left, y, rowWidth, 1);
tileBufferOffset += bytesPerTileRow;
uncompressedPixelBufferOffset += bytesPerRow;
}

remainingPixelsInRow -= tileWidth;
tileIndex++;
}
}

colorDecoder.Decode(uncompressedPixelBufferSpan, pixels, 0, 0, width, height);
}

private TiffBaseColorDecoder<TPixel> CreateChunkyColorDecoder<TPixel>()
Expand Down
Loading