Browse Source

Parse T4 Options: honor eol padding, if present

pull/1570/head
Brian Popow 5 years ago
parent
commit
0e5938f92a
  1. 36
      src/ImageSharp/Formats/Tiff/Compression/FaxCompressionOptions.cs
  2. 4
      src/ImageSharp/Formats/Tiff/Compression/ModifiedHuffmanTiffCompression.cs
  3. 74
      src/ImageSharp/Formats/Tiff/Compression/T4BitReader.cs
  4. 17
      src/ImageSharp/Formats/Tiff/Compression/T4TiffCompression.cs
  5. 11
      src/ImageSharp/Formats/Tiff/Compression/TiffCompressionFactory.cs
  6. 2
      src/ImageSharp/Formats/Tiff/README.md
  7. 16
      src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs
  8. 13
      src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs
  9. 2
      tests/ImageSharp.Benchmarks/Codecs/DecodeTiff.cs
  10. 41
      tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs
  11. 1
      tests/ImageSharp.Tests/TestImages.cs
  12. 3
      tests/Images/Input/Tiff/Calliphora_ccitt_fax3_with_eol_padding.tiff

36
src/ImageSharp/Formats/Tiff/Compression/FaxCompressionOptions.cs

@ -0,0 +1,36 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System;
namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression
{
/// <summary>
/// Fax compression options, see TIFF spec page 51f (T4Options).
/// </summary>
[Flags]
public enum FaxCompressionOptions : uint
{
/// <summary>
/// No options.
/// </summary>
None = 0,
/// <summary>
/// If set, 2-dimensional coding is used (otherwise 1-dimensional is assumed).
/// </summary>
TwoDimensionalCoding = 1,
/// <summary>
/// If set, uncompressed mode is used.
/// </summary>
UncompressedMode = 2,
/// <summary>
/// If set, fill bits have been added as necessary before EOL codes such that
/// EOL always ends on a byte boundary, thus ensuring an EOL-sequence of 1 byte
/// preceded by a zero nibble: xxxx-0000 0000-0001.
/// </summary>
EolPadding = 4
}
}

4
src/ImageSharp/Formats/Tiff/Compression/ModifiedHuffmanTiffCompression.cs

@ -21,7 +21,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression
/// <param name="photometricInterpretation">The photometric interpretation.</param>
/// <param name="width">The image width.</param>
public ModifiedHuffmanTiffCompression(MemoryAllocator allocator, TiffPhotometricInterpretation photometricInterpretation, int width)
: base(allocator, photometricInterpretation, width)
: base(allocator, FaxCompressionOptions.None, photometricInterpretation, width)
{
}
@ -32,7 +32,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression
byte whiteValue = (byte)(isWhiteZero ? 0 : 1);
byte blackValue = (byte)(isWhiteZero ? 1 : 0);
using var bitReader = new T4BitReader(stream, byteCount, this.Allocator, isModifiedHuffman: true);
using var bitReader = new T4BitReader(stream, byteCount, this.Allocator, eolPadding: false, isModifiedHuffman: true);
buffer.Clear();
uint bitsWritten = 0;

74
src/ImageSharp/Formats/Tiff/Compression/T4BitReader.cs

@ -35,11 +35,6 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression
/// </summary>
private ulong position;
/// <summary>
/// Indicates, if the current run are white pixels.
/// </summary>
private bool isWhiteRun;
/// <summary>
/// Indicates whether its the first line of data which is read from the image.
/// </summary>
@ -50,24 +45,27 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression
/// </summary>
private bool terminationCodeFound;
/// <summary>
/// Number of pixels in the current run.
/// </summary>
private uint runLength;
/// <summary>
/// We keep track if its the start of the row, because each run is expected to start with a white run.
/// If the image row itself starts with black, a white run of zero is expected.
/// </summary>
private bool isStartOfRow;
/// <summary>
/// Indicates whether the modified huffman compression, as specified in the TIFF spec in section 10, is used.
/// </summary>
private readonly bool isModifiedHuffmanRle;
/// <summary>
/// Indicates, if fill bits have been added as necessary before EOL codes such that EOL always ends on a byte boundary. Defaults to false.
/// </summary>
private readonly bool eolPadding;
private readonly int dataLength;
private const int MinCodeLength = 2;
private const int MaxCodeLength = 13;
private readonly int maxCodeLength = 13;
private static readonly Dictionary<uint, uint> WhiteLen4TermCodes = new Dictionary<uint, uint>()
{
@ -225,8 +223,9 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression
/// <param name="input">The compressed input stream.</param>
/// <param name="bytesToRead">The number of bytes to read from the stream.</param>
/// <param name="allocator">The memory allocator.</param>
/// <param name="isModifiedHuffman">Indicates, if its the modified huffman code variation.</param>
public T4BitReader(Stream input, int bytesToRead, MemoryAllocator allocator, bool isModifiedHuffman = false)
/// <param name="eolPadding">Indicates, if fill bits have been added as necessary before EOL codes such that EOL always ends on a byte boundary. Defaults to false.</param>
/// <param name="isModifiedHuffman">Indicates, if its the modified huffman code variation. Defaults to false.</param>
public T4BitReader(Stream input, int bytesToRead, MemoryAllocator allocator, bool eolPadding = false, bool isModifiedHuffman = false)
{
this.Data = allocator.Allocate<byte>(bytesToRead);
this.ReadImageDataFromStream(input, bytesToRead);
@ -237,11 +236,17 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression
this.value = 0;
this.curValueBitsRead = 0;
this.position = 0;
this.isWhiteRun = true;
this.IsWhiteRun = true;
this.isFirstScanLine = true;
this.isStartOfRow = true;
this.terminationCodeFound = false;
this.runLength = 0;
this.RunLength = 0;
this.eolPadding = eolPadding;
if (this.eolPadding)
{
this.maxCodeLength = 24;
}
}
/// <summary>
@ -268,17 +273,28 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression
/// <summary>
/// Gets a value indicating whether the current run is a white pixel run, otherwise its a black pixel run.
/// </summary>
public bool IsWhiteRun => this.isWhiteRun;
public bool IsWhiteRun { get; private set; }
/// <summary>
/// Gets the number of pixels in the current run.
/// </summary>
public uint RunLength => this.runLength;
public uint RunLength { get; private set; }
/// <summary>
/// Gets a value indicating whether the end of a pixel row has been reached.
/// </summary>
public bool IsEndOfScanLine => this.curValueBitsRead == 12 && this.value == 1;
public bool IsEndOfScanLine
{
get
{
if (this.eolPadding)
{
return this.curValueBitsRead >= 12 && this.value == 1;
}
return this.curValueBitsRead == 12 && this.value == 1;
}
}
/// <summary>
/// Read the next run of pixels.
@ -287,7 +303,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression
{
if (this.terminationCodeFound)
{
this.isWhiteRun = !this.IsWhiteRun;
this.IsWhiteRun = !this.IsWhiteRun;
this.terminationCodeFound = false;
}
@ -296,7 +312,8 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression
if (this.isFirstScanLine && !this.isModifiedHuffmanRle)
{
// We expect an EOL before the first data.
this.value = this.ReadValue(12);
this.value = this.ReadValue(this.eolPadding ? 16 : 12);
if (!this.IsEndOfScanLine)
{
TiffThrowHelper.ThrowImageFormatException("t4 parsing error: expected start of data marker not found");
@ -310,7 +327,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression
do
{
if (this.curValueBitsRead > MaxCodeLength)
if (this.curValueBitsRead > this.maxCodeLength)
{
TiffThrowHelper.ThrowImageFormatException("t4 parsing error: invalid code length read");
}
@ -320,11 +337,11 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression
{
if (this.IsWhiteRun)
{
this.runLength += this.WhiteMakeupCodeRunLength();
this.RunLength += this.WhiteMakeupCodeRunLength();
}
else
{
this.runLength += this.BlackMakeupCodeRunLength();
this.RunLength += this.BlackMakeupCodeRunLength();
}
this.isStartOfRow = false;
@ -338,7 +355,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression
// Each line starts with a white run. If the image starts with black, a white run with length zero is written.
if (this.isStartOfRow && this.IsWhiteRun && this.WhiteTerminatingCodeRunLength() == 0)
{
this.isWhiteRun = !this.IsWhiteRun;
this.IsWhiteRun = !this.IsWhiteRun;
this.Reset();
this.isStartOfRow = false;
continue;
@ -346,11 +363,11 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression
if (this.IsWhiteRun)
{
this.runLength += this.WhiteTerminatingCodeRunLength();
this.RunLength += this.WhiteTerminatingCodeRunLength();
}
else
{
this.runLength += this.BlackTerminatingCodeRunLength();
this.RunLength += this.BlackTerminatingCodeRunLength();
}
this.terminationCodeFound = true;
@ -374,7 +391,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression
public void StartNewRow()
{
// Each new row starts with a white run.
this.isWhiteRun = true;
this.IsWhiteRun = true;
this.isStartOfRow = true;
this.terminationCodeFound = false;
@ -770,14 +787,13 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression
if (resetRunLength)
{
this.runLength = 0;
this.RunLength = 0;
}
}
private uint ReadValue(int nBits)
{
Guard.MustBeGreaterThan(nBits, 0, nameof(nBits));
Guard.MustBeLessThanOrEqualTo(nBits, 12, nameof(nBits));
uint v = 0;
int shift = nBits;

17
src/ImageSharp/Formats/Tiff/Compression/T4TiffCompression.cs

@ -14,25 +14,32 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression
/// </summary>
internal class T4TiffCompression : TiffBaseCompression
{
private readonly FaxCompressionOptions faxCompressionOptions;
/// <summary>
/// Initializes a new instance of the <see cref="T4TiffCompression" /> class.
/// </summary>
/// <param name="allocator">The memory allocator.</param>
/// <param name="faxOptions">Fax compression options.</param>
/// <param name="photometricInterpretation">The photometric interpretation.</param>
/// <param name="width">The image width.</param>
public T4TiffCompression(MemoryAllocator allocator, TiffPhotometricInterpretation photometricInterpretation, int width)
: base(allocator, photometricInterpretation, width)
{
}
public T4TiffCompression(MemoryAllocator allocator, FaxCompressionOptions faxOptions, TiffPhotometricInterpretation photometricInterpretation, int width)
: base(allocator, photometricInterpretation, width) => this.faxCompressionOptions = faxOptions;
/// <inheritdoc/>
protected override void Decompress(BufferedReadStream stream, int byteCount, Span<byte> buffer)
{
if (this.faxCompressionOptions.HasFlag(FaxCompressionOptions.TwoDimensionalCoding))
{
TiffThrowHelper.ThrowNotSupported("TIFF CCITT 2D compression is not yet supported");
}
bool isWhiteZero = this.PhotometricInterpretation == TiffPhotometricInterpretation.WhiteIsZero;
byte whiteValue = (byte)(isWhiteZero ? 0 : 1);
byte blackValue = (byte)(isWhiteZero ? 1 : 0);
using var bitReader = new T4BitReader(stream, byteCount, this.Allocator);
var eolPadding = this.faxCompressionOptions.HasFlag(FaxCompressionOptions.EolPadding);
using var bitReader = new T4BitReader(stream, byteCount, this.Allocator, eolPadding);
buffer.Clear();
uint bitsWritten = 0;

11
src/ImageSharp/Formats/Tiff/Compression/TiffCompressionFactory.cs

@ -8,7 +8,14 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression
{
internal static class TiffCompressionFactory
{
public static TiffBaseCompression Create(TiffDecoderCompressionType compressionType, MemoryAllocator allocator, TiffPhotometricInterpretation photometricInterpretation, int width, int bitsPerPixel, TiffPredictor predictor)
public static TiffBaseCompression Create(
TiffDecoderCompressionType compressionType,
MemoryAllocator allocator,
TiffPhotometricInterpretation photometricInterpretation,
int width,
int bitsPerPixel,
TiffPredictor predictor,
FaxCompressionOptions faxOptions)
{
switch (compressionType)
{
@ -28,7 +35,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression
case TiffDecoderCompressionType.T4:
DebugGuard.IsTrue(predictor == TiffPredictor.None, "predictor");
return new T4TiffCompression(allocator, photometricInterpretation, width);
return new T4TiffCompression(allocator, faxOptions, photometricInterpretation, width);
case TiffDecoderCompressionType.HuffmanRle:
DebugGuard.IsTrue(predictor == TiffPredictor.None, "predictor");

2
src/ImageSharp/Formats/Tiff/README.md

@ -121,7 +121,7 @@ Decoder:
|PageName | | | |
|XPosition | | | |
|YPosition | | | |
|T4Options | | | |
|T4Options | | Y | |
|T6Options | | | |
|PageNumber | | | |
|TransferFunction | | | |

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

@ -22,7 +22,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
internal class TiffDecoderCore : IImageDecoderInternals
{
/// <summary>
/// The global configuration
/// The global configuration.
/// </summary>
private readonly Configuration configuration;
@ -60,6 +60,9 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
/// </summary>
public ushort[] BitsPerSample { get; set; }
/// <summary>
/// Gets or sets the bits per pixel.
/// </summary>
public int BitsPerPixel { get; set; }
/// <summary>
@ -77,6 +80,11 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
/// </summary>
public TiffDecoderCompressionType CompressionType { get; set; }
/// <summary>
/// Gets or sets the Fax specific compression options.
/// </summary>
public FaxCompressionOptions FaxCompressionOptions { get; set; }
/// <summary>
/// Gets or sets the planar configuration type to use when decoding the image.
/// </summary>
@ -88,7 +96,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
public TiffPhotometricInterpretation PhotometricInterpretation { get; set; }
/// <summary>
/// Gets or sets the predictor.
/// Gets or sets the horizontal predictor.
/// </summary>
public TiffPredictor Predictor { get; set; }
@ -284,7 +292,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
stripBuffers[stripIndex] = this.memoryAllocator.AllocateManagedByteBuffer(uncompressedStripSize);
}
TiffBaseCompression decompressor = TiffCompressionFactory.Create(this.CompressionType, this.memoryAllocator, this.PhotometricInterpretation, width, bitsPerPixel, this.Predictor);
TiffBaseCompression decompressor = TiffCompressionFactory.Create(this.CompressionType, this.memoryAllocator, this.PhotometricInterpretation, width, bitsPerPixel, this.Predictor, this.FaxCompressionOptions);
RgbPlanarTiffColor<TPixel> colorDecoder = TiffColorDecoderFactory<TPixel>.CreatePlanar(this.ColorType, this.BitsPerSample, this.ColorMap);
@ -321,7 +329,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
Buffer2D<TPixel> pixels = frame.PixelBuffer;
TiffBaseCompression decompressor = TiffCompressionFactory.Create(this.CompressionType, this.memoryAllocator, this.PhotometricInterpretation, width, bitsPerPixel, this.Predictor);
TiffBaseCompression decompressor = TiffCompressionFactory.Create(this.CompressionType, this.memoryAllocator, this.PhotometricInterpretation, width, bitsPerPixel, this.Predictor, this.FaxCompressionOptions);
TiffBaseColorDecoder<TPixel> colorDecoder = TiffColorDecoderFactory<TPixel>.Create(this.ColorType, this.BitsPerSample, this.ColorMap);

13
src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs

@ -1,6 +1,7 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression;
using SixLabors.ImageSharp.Formats.Experimental.Tiff.Constants;
using SixLabors.ImageSharp.Metadata.Profiles.Exif;
@ -57,7 +58,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
options.BitsPerPixel = entries.BitsPerPixel;
ParseColorType(options, entries);
ParseCompression(options, entries.Compression);
ParseCompression(options, entries);
}
private static void ParseColorType(this TiffDecoderCore options, TiffFrameMetadata entries)
@ -208,8 +209,9 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
}
}
private static void ParseCompression(this TiffDecoderCore options, TiffCompression compression)
private static void ParseCompression(this TiffDecoderCore options, TiffFrameMetadata entries)
{
TiffCompression compression = entries.Compression;
switch (compression)
{
case TiffCompression.None:
@ -240,6 +242,13 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
case TiffCompression.CcittGroup3Fax:
{
options.CompressionType = TiffDecoderCompressionType.T4;
IExifValue t4options = entries.FrameTags.Find(tag => tag.Tag == ExifTag.T4Options);
if (t4options != null)
{
var t4OptionValue = (FaxCompressionOptions)t4options.GetValue();
options.FaxCompressionOptions = t4OptionValue;
}
break;
}

2
tests/ImageSharp.Benchmarks/Codecs/DecodeTiff.cs

@ -3,7 +3,7 @@
// Enable this for using larger Tiff files. Those files are very large (> 700MB) and therefor not part of the git repo.
// Use the scripts gen_big.ps1 and gen_medium.ps1 in tests\Images\Input\Tiff\Benchmarks to generate those images.
// #define BIG_TESTS
//// #define BIG_TESTS
using System.IO;

41
tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs

@ -39,10 +39,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
[Theory]
[WithFileCollection(nameof(NotSupportedImages), PixelTypes.Rgba32)]
public void ThrowsNotSupported<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
Assert.Throws<NotSupportedException>(() => provider.GetImage(TiffDecoder));
}
where TPixel : unmanaged, IPixel<TPixel> => Assert.Throws<NotSupportedException>(() => provider.GetImage(TiffDecoder));
[Theory]
[InlineData(TestImages.Tiff.RgbUncompressed, 24, 256, 256, 300, 300, PixelResolutionUnit.PixelsPerInch)]
@ -91,10 +88,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
[WithFile(Calliphora_RgbUncompressed, PixelTypes.Rgba32)]
[WithFile(Calliphora_BiColorUncompressed, PixelTypes.Rgba32)]
public void TiffDecoder_CanDecode_Uncompressed<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
TestTiffDecoder(provider);
}
where TPixel : unmanaged, IPixel<TPixel> => TestTiffDecoder(provider);
[Theory]
[WithFile(Calliphora_PaletteUncompressed, PixelTypes.Rgba32)]
@ -103,10 +97,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
[WithFile(RgbPaletteDeflate, PixelTypes.Rgba32)]
[WithFile(PaletteUncompressed, PixelTypes.Rgba32)]
public void TiffDecoder_CanDecode_WithPalette<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
TestTiffDecoder(provider);
}
where TPixel : unmanaged, IPixel<TPixel> => TestTiffDecoder(provider);
[Theory]
[WithFile(GrayscaleDeflateMultistrip, PixelTypes.Rgba32)]
@ -118,10 +109,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
[WithFile(RgbDeflatePredictor, PixelTypes.Rgba32)]
[WithFile(SmallRgbDeflate, PixelTypes.Rgba32)]
public void TiffDecoder_CanDecode_DeflateCompressed<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
TestTiffDecoder(provider);
}
where TPixel : unmanaged, IPixel<TPixel> => TestTiffDecoder(provider);
[Theory]
[WithFile(RgbLzwPredictor, PixelTypes.Rgba32)]
@ -134,10 +122,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
[WithFile(Calliphora_GrayscaleLzw_Predictor, PixelTypes.Rgba32)]
[WithFile(SmallRgbLzw, PixelTypes.Rgba32)]
public void TiffDecoder_CanDecode_LzwCompressed<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
TestTiffDecoder(provider);
}
where TPixel : unmanaged, IPixel<TPixel> => TestTiffDecoder(provider);
[Theory]
[WithFile(HuffmanRleAllTermCodes, PixelTypes.Rgba32)]
@ -145,30 +130,22 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
[WithFile(HuffmanRle_basi3p02, PixelTypes.Rgba32)]
[WithFile(Calliphora_HuffmanCompressed, PixelTypes.Rgba32)]
public void TiffDecoder_CanDecode_HuffmanCompressed<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
TestTiffDecoder(provider);
}
where TPixel : unmanaged, IPixel<TPixel> => TestTiffDecoder(provider);
[Theory]
[WithFile(CcittFax3AllTermCodes, PixelTypes.Rgba32)]
[WithFile(CcittFax3AllMakeupCodes, PixelTypes.Rgba32)]
[WithFile(Calliphora_Fax3Compressed, PixelTypes.Rgba32)]
[WithFile(Calliphora_Fax3Compressed_WithEolPadding, PixelTypes.Rgba32)]
public void TiffDecoder_CanDecode_Fax3Compressed<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
TestTiffDecoder(provider);
}
where TPixel : unmanaged, IPixel<TPixel> => TestTiffDecoder(provider);
[Theory]
[WithFile(Calliphora_RgbPackbits, PixelTypes.Rgba32)]
[WithFile(RgbPackbits, PixelTypes.Rgba32)]
[WithFile(RgbPackbitsMultistrip, PixelTypes.Rgba32)]
public void TiffDecoder_CanDecode_PackBitsCompressed<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
TestTiffDecoder(provider);
}
where TPixel : unmanaged, IPixel<TPixel> => TestTiffDecoder(provider);
[Theory]
[WithFileCollection(nameof(MultiframeTestImages), PixelTypes.Rgba32)]

1
tests/ImageSharp.Tests/TestImages.cs

@ -522,6 +522,7 @@ namespace SixLabors.ImageSharp.Tests
public const string Calliphora_RgbPackbits = "Tiff/Calliphora_rgb_packbits.tiff";
public const string Calliphora_RgbUncompressed = "Tiff/Calliphora_rgb_uncompressed.tiff";
public const string Calliphora_Fax3Compressed = "Tiff/Calliphora_ccitt_fax3.tiff";
public const string Calliphora_Fax3Compressed_WithEolPadding = "Tiff/Calliphora_ccitt_fax3_with_eol_padding.tiff";
public const string Calliphora_Fax4Compressed = "Tiff/Calliphora_ccitt_fax4.tiff";
public const string Calliphora_HuffmanCompressed = "Tiff/Calliphora_huffman_rle.tiff";
public const string Calliphora_BiColorUncompressed = "Tiff/Calliphora_bicolor_uncompressed.tiff";

3
tests/Images/Input/Tiff/Calliphora_ccitt_fax3_with_eol_padding.tiff

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:15e0f4f04699c7253ce422a7741ada192615182da53e9fd86bdf547cd991b290
size 126382
Loading…
Cancel
Save