Skip to content

Commit 18f8de9

Browse files
committed
Do not ignore tileHeight when undoing horizontal predictor
1 parent 8f97280 commit 18f8de9

File tree

7 files changed

+26
-15
lines changed

7 files changed

+26
-15
lines changed

src/ImageSharp/Formats/Tiff/Compression/Decompressors/DeflateTiffCompression.cs

+6-2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ internal sealed class DeflateTiffCompression : TiffBaseDecompressor
2626

2727
private readonly int tileWidth;
2828

29+
private readonly int tileHeight;
30+
2931
/// <summary>
3032
/// Initializes a new instance of the <see cref="DeflateTiffCompression" /> class.
3133
/// </summary>
@@ -37,13 +39,15 @@ internal sealed class DeflateTiffCompression : TiffBaseDecompressor
3739
/// <param name="isBigEndian">if set to <c>true</c> decodes the pixel data as big endian, otherwise as little endian.</param>
3840
/// <param name="isTiled">Flag indicates, if the image is a tiled image.</param>
3941
/// <param name="tileWidth">Number of pixels in a tile row.</param>
40-
public DeflateTiffCompression(MemoryAllocator memoryAllocator, int width, int bitsPerPixel, TiffColorType colorType, TiffPredictor predictor, bool isBigEndian, bool isTiled, int tileWidth)
42+
/// <param name="tileHeight">Number of rows in a tile.</param>
43+
public DeflateTiffCompression(MemoryAllocator memoryAllocator, int width, int bitsPerPixel, TiffColorType colorType, TiffPredictor predictor, bool isBigEndian, bool isTiled, int tileWidth, int tileHeight)
4144
: base(memoryAllocator, width, bitsPerPixel, predictor)
4245
{
4346
this.colorType = colorType;
4447
this.isBigEndian = isBigEndian;
4548
this.isTiled = isTiled;
4649
this.tileWidth = tileWidth;
50+
this.tileHeight = tileHeight;
4751
}
4852

4953
/// <inheritdoc/>
@@ -81,7 +85,7 @@ protected override void Decompress(BufferedReadStream stream, int byteCount, int
8185
if (this.isTiled)
8286
{
8387
// When the image is tiled, undoing the horizontal predictor will be done for each tile row.
84-
HorizontalPredictor.UndoTile(buffer, this.tileWidth, this.colorType, this.isBigEndian);
88+
HorizontalPredictor.UndoTile(buffer, this.tileWidth, this.tileHeight, this.colorType, this.isBigEndian);
8589
}
8690
else
8791
{

src/ImageSharp/Formats/Tiff/Compression/Decompressors/LzwTiffCompression.cs

+6-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ internal sealed class LzwTiffCompression : TiffBaseDecompressor
2121

2222
private readonly int tileWidth;
2323

24+
private readonly int tileHeight;
25+
2426
/// <summary>
2527
/// Initializes a new instance of the <see cref="LzwTiffCompression" /> class.
2628
/// </summary>
@@ -32,13 +34,15 @@ internal sealed class LzwTiffCompression : TiffBaseDecompressor
3234
/// <param name="isBigEndian">if set to <c>true</c> decodes the pixel data as big endian, otherwise as little endian.</param>
3335
/// <param name="isTiled">Flag indicates, if the image is a tiled image.</param>
3436
/// <param name="tileWidth">Number of pixels in a tile row.</param>
35-
public LzwTiffCompression(MemoryAllocator memoryAllocator, int width, int bitsPerPixel, TiffColorType colorType, TiffPredictor predictor, bool isBigEndian, bool isTiled, int tileWidth)
37+
/// <param name="tileHeight">Number of rows in a tile.</param>
38+
public LzwTiffCompression(MemoryAllocator memoryAllocator, int width, int bitsPerPixel, TiffColorType colorType, TiffPredictor predictor, bool isBigEndian, bool isTiled, int tileWidth, int tileHeight)
3639
: base(memoryAllocator, width, bitsPerPixel, predictor)
3740
{
3841
this.colorType = colorType;
3942
this.isBigEndian = isBigEndian;
4043
this.isTiled = isTiled;
4144
this.tileWidth = tileWidth;
45+
this.tileHeight = tileHeight;
4246
}
4347

4448
/// <inheritdoc/>
@@ -52,7 +56,7 @@ protected override void Decompress(BufferedReadStream stream, int byteCount, int
5256
if (this.isTiled)
5357
{
5458
// When the image is tiled, undoing the horizontal predictor will be done for each tile row.
55-
HorizontalPredictor.UndoTile(buffer, this.tileWidth, this.colorType, this.isBigEndian);
59+
HorizontalPredictor.UndoTile(buffer, this.tileWidth, this.tileHeight, this.colorType, this.isBigEndian);
5660
}
5761
else
5862
{

src/ImageSharp/Formats/Tiff/Compression/HorizontalPredictor.cs

+4-3
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,13 @@ public static void Undo(Span<byte> pixelBytes, int width, TiffColorType colorTyp
6666
/// Inverts the horizontal predictor for each tile row.
6767
/// </summary>
6868
/// <param name="pixelBytes">Buffer with decompressed pixel data for a tile.</param>
69-
/// <param name="tileWidth">Tile with in pixels.</param>
69+
/// <param name="tileWidth">Tile width in pixels.</param>
70+
/// <param name="tileHeight">Tile height in pixels.</param>
7071
/// <param name="colorType">The color type of the pixel data.</param>
7172
/// <param name="isBigEndian">If set to <c>true</c> decodes the pixel data as big endian, otherwise as little endian.</param>
72-
public static void UndoTile(Span<byte> pixelBytes, int tileWidth, TiffColorType colorType, bool isBigEndian)
73+
public static void UndoTile(Span<byte> pixelBytes, int tileWidth, int tileHeight, TiffColorType colorType, bool isBigEndian)
7374
{
74-
for (int y = 0; y < tileWidth; y++)
75+
for (int y = 0; y < tileHeight; y++)
7576
{
7677
UndoRow(pixelBytes, tileWidth, y, colorType, isBigEndian);
7778
}

src/ImageSharp/Formats/Tiff/Compression/TiffDecompressorsFactory.cs

+4-3
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ public static TiffBaseDecompressor Create(
2525
TiffFillOrder fillOrder,
2626
ByteOrder byteOrder,
2727
bool isTiled = false,
28-
int tileWidth = 0)
28+
int tileWidth = 0,
29+
int tileHeight = 0)
2930
{
3031
switch (method)
3132
{
@@ -41,11 +42,11 @@ public static TiffBaseDecompressor Create(
4142

4243
case TiffDecoderCompressionType.Deflate:
4344
DebugGuard.IsTrue(faxOptions == FaxCompressionOptions.None, "No fax compression options are expected");
44-
return new DeflateTiffCompression(allocator, width, bitsPerPixel, colorType, predictor, byteOrder == ByteOrder.BigEndian, isTiled, tileWidth);
45+
return new DeflateTiffCompression(allocator, width, bitsPerPixel, colorType, predictor, byteOrder == ByteOrder.BigEndian, isTiled, tileWidth, tileHeight);
4546

4647
case TiffDecoderCompressionType.Lzw:
4748
DebugGuard.IsTrue(faxOptions == FaxCompressionOptions.None, "No fax compression options are expected");
48-
return new LzwTiffCompression(allocator, width, bitsPerPixel, colorType, predictor, byteOrder == ByteOrder.BigEndian, isTiled, tileWidth);
49+
return new LzwTiffCompression(allocator, width, bitsPerPixel, colorType, predictor, byteOrder == ByteOrder.BigEndian, isTiled, tileWidth, tileHeight);
4950

5051
case TiffDecoderCompressionType.T4:
5152
DebugGuard.IsTrue(predictor == TiffPredictor.None, "Predictor should only be used with lzw or deflate compression");

src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs

+4-3
Original file line numberDiff line numberDiff line change
@@ -679,7 +679,7 @@ private void DecodeTilesChunky<TPixel>(
679679
using IMemoryOwner<byte> tileBuffer = this.memoryAllocator.Allocate<byte>(bytesPerTileRow * tileLength, AllocationOptions.Clean);
680680
Span<byte> tileBufferSpan = tileBuffer.GetSpan();
681681

682-
using TiffBaseDecompressor decompressor = this.CreateDecompressor<TPixel>(frame.Width, bitsPerPixel, true, tileWidth);
682+
using TiffBaseDecompressor decompressor = this.CreateDecompressor<TPixel>(frame.Width, bitsPerPixel, true, tileWidth, tileLength);
683683
TiffBaseColorDecoder<TPixel> colorDecoder = this.CreateChunkyColorDecoder<TPixel>();
684684

685685
int tileIndex = 0;
@@ -747,7 +747,7 @@ private TiffBasePlanarColorDecoder<TPixel> CreatePlanarColorDecoder<TPixel>()
747747
this.YcbcrSubSampling,
748748
this.byteOrder);
749749

750-
private TiffBaseDecompressor CreateDecompressor<TPixel>(int frameWidth, int bitsPerPixel, bool isTiled = false, int tileWidth = 0)
750+
private TiffBaseDecompressor CreateDecompressor<TPixel>(int frameWidth, int bitsPerPixel, bool isTiled = false, int tileWidth = 0, int tileHeight = 0)
751751
where TPixel : unmanaged, IPixel<TPixel> =>
752752
TiffDecompressorsFactory.Create(
753753
this.Options,
@@ -764,7 +764,8 @@ private TiffBaseDecompressor CreateDecompressor<TPixel>(int frameWidth, int bits
764764
this.FillOrder,
765765
this.byteOrder,
766766
isTiled,
767-
tileWidth);
767+
tileWidth,
768+
tileHeight);
768769

769770
private IMemoryOwner<ulong> ConvertNumbers(Array array, out Span<ulong> span)
770771
{

tests/ImageSharp.Tests/Formats/Tiff/Compression/DeflateTiffCompressionTests.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public void Compress_Decompress_Roundtrip_Works(byte[] data)
2323
using BufferedReadStream stream = CreateCompressedStream(data);
2424
byte[] buffer = new byte[data.Length];
2525

26-
using var decompressor = new DeflateTiffCompression(Configuration.Default.MemoryAllocator, 10, 8, TiffColorType.BlackIsZero8, TiffPredictor.None, false, false, 0);
26+
using var decompressor = new DeflateTiffCompression(Configuration.Default.MemoryAllocator, 10, 8, TiffColorType.BlackIsZero8, TiffPredictor.None, false, false, 0, 0);
2727

2828
decompressor.Decompress(stream, 0, (uint)stream.Length, 1, buffer, default);
2929

tests/ImageSharp.Tests/Formats/Tiff/Compression/LzwTiffCompressionTests.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public void Compress_Decompress_Roundtrip_Works(byte[] data)
3737
using BufferedReadStream stream = CreateCompressedStream(data);
3838
byte[] buffer = new byte[data.Length];
3939

40-
using var decompressor = new LzwTiffCompression(Configuration.Default.MemoryAllocator, 10, 8, TiffColorType.BlackIsZero8, TiffPredictor.None, false, false, 0);
40+
using var decompressor = new LzwTiffCompression(Configuration.Default.MemoryAllocator, 10, 8, TiffColorType.BlackIsZero8, TiffPredictor.None, false, false, 0, 0);
4141
decompressor.Decompress(stream, 0, (uint)stream.Length, 1, buffer, default);
4242

4343
Assert.Equal(data, buffer);

0 commit comments

Comments
 (0)