Browse Source

Do not ignore tileHeight when undoing horizontal predictor

pull/2878/head
Brian Popow 12 months ago
parent
commit
18f8de983e
  1. 8
      src/ImageSharp/Formats/Tiff/Compression/Decompressors/DeflateTiffCompression.cs
  2. 8
      src/ImageSharp/Formats/Tiff/Compression/Decompressors/LzwTiffCompression.cs
  3. 7
      src/ImageSharp/Formats/Tiff/Compression/HorizontalPredictor.cs
  4. 7
      src/ImageSharp/Formats/Tiff/Compression/TiffDecompressorsFactory.cs
  5. 7
      src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs
  6. 2
      tests/ImageSharp.Tests/Formats/Tiff/Compression/DeflateTiffCompressionTests.cs
  7. 2
      tests/ImageSharp.Tests/Formats/Tiff/Compression/LzwTiffCompressionTests.cs

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

@ -26,6 +26,8 @@ internal sealed class DeflateTiffCompression : TiffBaseDecompressor
private readonly int tileWidth;
private readonly int tileHeight;
/// <summary>
/// Initializes a new instance of the <see cref="DeflateTiffCompression" /> class.
/// </summary>
@ -37,13 +39,15 @@ internal sealed class DeflateTiffCompression : TiffBaseDecompressor
/// <param name="isBigEndian">if set to <c>true</c> decodes the pixel data as big endian, otherwise as little endian.</param>
/// <param name="isTiled">Flag indicates, if the image is a tiled image.</param>
/// <param name="tileWidth">Number of pixels in a tile row.</param>
public DeflateTiffCompression(MemoryAllocator memoryAllocator, int width, int bitsPerPixel, TiffColorType colorType, TiffPredictor predictor, bool isBigEndian, bool isTiled, int tileWidth)
/// <param name="tileHeight">Number of rows in a tile.</param>
public DeflateTiffCompression(MemoryAllocator memoryAllocator, int width, int bitsPerPixel, TiffColorType colorType, TiffPredictor predictor, bool isBigEndian, bool isTiled, int tileWidth, int tileHeight)
: base(memoryAllocator, width, bitsPerPixel, predictor)
{
this.colorType = colorType;
this.isBigEndian = isBigEndian;
this.isTiled = isTiled;
this.tileWidth = tileWidth;
this.tileHeight = tileHeight;
}
/// <inheritdoc/>
@ -81,7 +85,7 @@ internal sealed class DeflateTiffCompression : TiffBaseDecompressor
if (this.isTiled)
{
// When the image is tiled, undoing the horizontal predictor will be done for each tile row.
HorizontalPredictor.UndoTile(buffer, this.tileWidth, this.colorType, this.isBigEndian);
HorizontalPredictor.UndoTile(buffer, this.tileWidth, this.tileHeight, this.colorType, this.isBigEndian);
}
else
{

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

@ -21,6 +21,8 @@ internal sealed class LzwTiffCompression : TiffBaseDecompressor
private readonly int tileWidth;
private readonly int tileHeight;
/// <summary>
/// Initializes a new instance of the <see cref="LzwTiffCompression" /> class.
/// </summary>
@ -32,13 +34,15 @@ internal sealed class LzwTiffCompression : TiffBaseDecompressor
/// <param name="isBigEndian">if set to <c>true</c> decodes the pixel data as big endian, otherwise as little endian.</param>
/// <param name="isTiled">Flag indicates, if the image is a tiled image.</param>
/// <param name="tileWidth">Number of pixels in a tile row.</param>
public LzwTiffCompression(MemoryAllocator memoryAllocator, int width, int bitsPerPixel, TiffColorType colorType, TiffPredictor predictor, bool isBigEndian, bool isTiled, int tileWidth)
/// <param name="tileHeight">Number of rows in a tile.</param>
public LzwTiffCompression(MemoryAllocator memoryAllocator, int width, int bitsPerPixel, TiffColorType colorType, TiffPredictor predictor, bool isBigEndian, bool isTiled, int tileWidth, int tileHeight)
: base(memoryAllocator, width, bitsPerPixel, predictor)
{
this.colorType = colorType;
this.isBigEndian = isBigEndian;
this.isTiled = isTiled;
this.tileWidth = tileWidth;
this.tileHeight = tileHeight;
}
/// <inheritdoc/>
@ -52,7 +56,7 @@ internal sealed class LzwTiffCompression : TiffBaseDecompressor
if (this.isTiled)
{
// When the image is tiled, undoing the horizontal predictor will be done for each tile row.
HorizontalPredictor.UndoTile(buffer, this.tileWidth, this.colorType, this.isBigEndian);
HorizontalPredictor.UndoTile(buffer, this.tileWidth, this.tileHeight, this.colorType, this.isBigEndian);
}
else
{

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

@ -66,12 +66,13 @@ internal static class HorizontalPredictor
/// Inverts the horizontal predictor for each tile row.
/// </summary>
/// <param name="pixelBytes">Buffer with decompressed pixel data for a tile.</param>
/// <param name="tileWidth">Tile with in pixels.</param>
/// <param name="tileWidth">Tile width in pixels.</param>
/// <param name="tileHeight">Tile height in pixels.</param>
/// <param name="colorType">The color type of the pixel data.</param>
/// <param name="isBigEndian">If set to <c>true</c> decodes the pixel data as big endian, otherwise as little endian.</param>
public static void UndoTile(Span<byte> pixelBytes, int tileWidth, TiffColorType colorType, bool isBigEndian)
public static void UndoTile(Span<byte> pixelBytes, int tileWidth, int tileHeight, TiffColorType colorType, bool isBigEndian)
{
for (int y = 0; y < tileWidth; y++)
for (int y = 0; y < tileHeight; y++)
{
UndoRow(pixelBytes, tileWidth, y, colorType, isBigEndian);
}

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

@ -25,7 +25,8 @@ internal static class TiffDecompressorsFactory
TiffFillOrder fillOrder,
ByteOrder byteOrder,
bool isTiled = false,
int tileWidth = 0)
int tileWidth = 0,
int tileHeight = 0)
{
switch (method)
{
@ -41,11 +42,11 @@ internal static class TiffDecompressorsFactory
case TiffDecoderCompressionType.Deflate:
DebugGuard.IsTrue(faxOptions == FaxCompressionOptions.None, "No fax compression options are expected");
return new DeflateTiffCompression(allocator, width, bitsPerPixel, colorType, predictor, byteOrder == ByteOrder.BigEndian, isTiled, tileWidth);
return new DeflateTiffCompression(allocator, width, bitsPerPixel, colorType, predictor, byteOrder == ByteOrder.BigEndian, isTiled, tileWidth, tileHeight);
case TiffDecoderCompressionType.Lzw:
DebugGuard.IsTrue(faxOptions == FaxCompressionOptions.None, "No fax compression options are expected");
return new LzwTiffCompression(allocator, width, bitsPerPixel, colorType, predictor, byteOrder == ByteOrder.BigEndian, isTiled, tileWidth);
return new LzwTiffCompression(allocator, width, bitsPerPixel, colorType, predictor, byteOrder == ByteOrder.BigEndian, isTiled, tileWidth, tileHeight);
case TiffDecoderCompressionType.T4:
DebugGuard.IsTrue(predictor == TiffPredictor.None, "Predictor should only be used with lzw or deflate compression");

7
src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs

@ -679,7 +679,7 @@ internal class TiffDecoderCore : ImageDecoderCore
using IMemoryOwner<byte> tileBuffer = this.memoryAllocator.Allocate<byte>(bytesPerTileRow * tileLength, AllocationOptions.Clean);
Span<byte> tileBufferSpan = tileBuffer.GetSpan();
using TiffBaseDecompressor decompressor = this.CreateDecompressor<TPixel>(frame.Width, bitsPerPixel, true, tileWidth);
using TiffBaseDecompressor decompressor = this.CreateDecompressor<TPixel>(frame.Width, bitsPerPixel, true, tileWidth, tileLength);
TiffBaseColorDecoder<TPixel> colorDecoder = this.CreateChunkyColorDecoder<TPixel>();
int tileIndex = 0;
@ -747,7 +747,7 @@ internal class TiffDecoderCore : ImageDecoderCore
this.YcbcrSubSampling,
this.byteOrder);
private TiffBaseDecompressor CreateDecompressor<TPixel>(int frameWidth, int bitsPerPixel, bool isTiled = false, int tileWidth = 0)
private TiffBaseDecompressor CreateDecompressor<TPixel>(int frameWidth, int bitsPerPixel, bool isTiled = false, int tileWidth = 0, int tileHeight = 0)
where TPixel : unmanaged, IPixel<TPixel> =>
TiffDecompressorsFactory.Create(
this.Options,
@ -764,7 +764,8 @@ internal class TiffDecoderCore : ImageDecoderCore
this.FillOrder,
this.byteOrder,
isTiled,
tileWidth);
tileWidth,
tileHeight);
private IMemoryOwner<ulong> ConvertNumbers(Array array, out Span<ulong> span)
{

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

@ -23,7 +23,7 @@ public class DeflateTiffCompressionTests
using BufferedReadStream stream = CreateCompressedStream(data);
byte[] buffer = new byte[data.Length];
using var decompressor = new DeflateTiffCompression(Configuration.Default.MemoryAllocator, 10, 8, TiffColorType.BlackIsZero8, TiffPredictor.None, false, false, 0);
using var decompressor = new DeflateTiffCompression(Configuration.Default.MemoryAllocator, 10, 8, TiffColorType.BlackIsZero8, TiffPredictor.None, false, false, 0, 0);
decompressor.Decompress(stream, 0, (uint)stream.Length, 1, buffer, default);

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

@ -37,7 +37,7 @@ public class LzwTiffCompressionTests
using BufferedReadStream stream = CreateCompressedStream(data);
byte[] buffer = new byte[data.Length];
using var decompressor = new LzwTiffCompression(Configuration.Default.MemoryAllocator, 10, 8, TiffColorType.BlackIsZero8, TiffPredictor.None, false, false, 0);
using var decompressor = new LzwTiffCompression(Configuration.Default.MemoryAllocator, 10, 8, TiffColorType.BlackIsZero8, TiffPredictor.None, false, false, 0, 0);
decompressor.Decompress(stream, 0, (uint)stream.Length, 1, buffer, default);
Assert.Equal(data, buffer);

Loading…
Cancel
Save