Skip to content

Commit b8d1cd8

Browse files
authored
Merge pull request #2874 from SixLabors/js/chunk-tiff-allocation
V3 : Decode Chunky Tile Rows Directly.
2 parents 313a7e8 + 49a1118 commit b8d1cd8

File tree

4 files changed

+25
-29
lines changed

4 files changed

+25
-29
lines changed

Diff for: .github/workflows/build-and-test.yml

+4-10
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ jobs:
6767

6868
steps:
6969
- name: Install libgdi+, which is required for tests running on ubuntu
70-
if: ${{ matrix.options.os == 'buildjet-4vcpu-ubuntu-2204-arm' }}
70+
if: ${{ contains(matrix.options.os, 'ubuntu') }}
7171
run: sudo apt-get -y install libgdiplus libgif-dev libglib2.0-dev libcairo2-dev libtiff-dev libexif-dev
7272

7373
- name: Git Config
@@ -108,18 +108,12 @@ jobs:
108108
restore-keys: ${{ runner.os }}-nuget-
109109

110110
- name: DotNet Setup
111-
if: ${{ matrix.options.sdk-preview != true }}
112-
uses: actions/setup-dotnet@v3
113-
with:
114-
dotnet-version: |
115-
6.0.x
116-
117-
- name: DotNet Setup Preview
118-
if: ${{ matrix.options.sdk-preview == true }}
119-
uses: actions/setup-dotnet@v3
111+
uses: actions/setup-dotnet@v4
120112
with:
121113
dotnet-version: |
114+
8.0.x
122115
7.0.x
116+
6.0.x
123117
124118
- name: DotNet Build
125119
if: ${{ matrix.options.sdk-preview != true }}

Diff for: .github/workflows/code-coverage.yml

+6-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ jobs:
1717
runs-on: ${{matrix.options.os}}
1818

1919
steps:
20+
- name: Install libgdi+, which is required for tests running on ubuntu
21+
run: sudo apt-get -y install libgdiplus libgif-dev libglib2.0-dev libcairo2-dev libtiff-dev libexif-dev
22+
2023
- name: Git Config
2124
shell: bash
2225
run: |
@@ -55,9 +58,11 @@ jobs:
5558
restore-keys: ${{ runner.os }}-nuget-
5659

5760
- name: DotNet Setup
58-
uses: actions/setup-dotnet@v3
61+
uses: actions/setup-dotnet@v4
5962
with:
6063
dotnet-version: |
64+
8.0.x
65+
7.0.x
6166
6.0.x
6267
6368
- name: DotNet Build

Diff for: 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]

Diff for: src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs

+14-17
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,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

Comments
 (0)