diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgba16PlanarTiffColor{TPixel}.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgba16PlanarTiffColor{TPixel}.cs
new file mode 100644
index 0000000000..705010ce90
--- /dev/null
+++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgba16PlanarTiffColor{TPixel}.cs
@@ -0,0 +1,75 @@
+// Copyright (c) Six Labors.
+// Licensed under the Apache License, Version 2.0.
+
+using System;
+using System.Buffers;
+using SixLabors.ImageSharp.Formats.Tiff.Utils;
+using SixLabors.ImageSharp.Memory;
+using SixLabors.ImageSharp.PixelFormats;
+
+namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation
+{
+ ///
+ /// Implements the 'RGB' photometric interpretation with an alpha channel and with 'Planar' layout for each color channel with 16 bit.
+ ///
+ internal class Rgba16PlanarTiffColor : TiffBasePlanarColorDecoder
+ where TPixel : unmanaged, IPixel
+ {
+ private readonly bool isBigEndian;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// if set to true decodes the pixel data as big endian, otherwise as little endian.
+ public Rgba16PlanarTiffColor(bool isBigEndian) => this.isBigEndian = isBigEndian;
+
+ ///
+ public override void Decode(IMemoryOwner[] data, Buffer2D pixels, int left, int top, int width, int height)
+ {
+ // Note: due to an issue with netcore 2.1 and default values and unpredictable behavior with those,
+ // we define our own defaults as a workaround. See: https://github.com/dotnet/runtime/issues/55623
+ Rgba64 rgba = TiffUtils.Rgba64Default;
+ var color = default(TPixel);
+ color.FromVector4(TiffUtils.Vector4Default);
+
+ Span redData = data[0].GetSpan();
+ Span greenData = data[1].GetSpan();
+ Span blueData = data[2].GetSpan();
+ Span alphaData = data[3].GetSpan();
+
+ int offset = 0;
+ for (int y = top; y < top + height; y++)
+ {
+ Span pixelRow = pixels.DangerousGetRowSpan(y).Slice(left, width);
+ if (this.isBigEndian)
+ {
+ for (int x = 0; x < pixelRow.Length; x++)
+ {
+ ulong r = TiffUtils.ConvertToUShortBigEndian(redData.Slice(offset, 2));
+ ulong g = TiffUtils.ConvertToUShortBigEndian(greenData.Slice(offset, 2));
+ ulong b = TiffUtils.ConvertToUShortBigEndian(blueData.Slice(offset, 2));
+ ulong a = TiffUtils.ConvertToUShortBigEndian(alphaData.Slice(offset, 2));
+
+ offset += 2;
+
+ pixelRow[x] = TiffUtils.ColorFromRgba64(rgba, r, g, b, a, color);
+ }
+ }
+ else
+ {
+ for (int x = 0; x < pixelRow.Length; x++)
+ {
+ ulong r = TiffUtils.ConvertToUShortLittleEndian(redData.Slice(offset, 2));
+ ulong g = TiffUtils.ConvertToUShortLittleEndian(greenData.Slice(offset, 2));
+ ulong b = TiffUtils.ConvertToUShortLittleEndian(blueData.Slice(offset, 2));
+ ulong a = TiffUtils.ConvertToUShortBigEndian(alphaData.Slice(offset, 2));
+
+ offset += 2;
+
+ pixelRow[x] = TiffUtils.ColorFromRgba64(rgba, r, g, b, a, color);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgba24PlanarTiffColor{TPixel}.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgba24PlanarTiffColor{TPixel}.cs
new file mode 100644
index 0000000000..654074b1b1
--- /dev/null
+++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgba24PlanarTiffColor{TPixel}.cs
@@ -0,0 +1,85 @@
+// Copyright (c) Six Labors.
+// Licensed under the Apache License, Version 2.0.
+
+using System;
+using System.Buffers;
+using SixLabors.ImageSharp.Formats.Tiff.Utils;
+using SixLabors.ImageSharp.Memory;
+using SixLabors.ImageSharp.PixelFormats;
+
+namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation
+{
+ ///
+ /// Implements the 'RGB' photometric interpretation with an alpha channel and with 'Planar' layout for each color channel with 24 bit.
+ ///
+ internal class Rgba24PlanarTiffColor : TiffBasePlanarColorDecoder
+ where TPixel : unmanaged, IPixel
+ {
+ private readonly bool isBigEndian;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// if set to true decodes the pixel data as big endian, otherwise as little endian.
+ public Rgba24PlanarTiffColor(bool isBigEndian) => this.isBigEndian = isBigEndian;
+
+ ///
+ public override void Decode(IMemoryOwner[] data, Buffer2D pixels, int left, int top, int width, int height)
+ {
+ // Note: due to an issue with netcore 2.1 and default values and unpredictable behavior with those,
+ // we define our own defaults as a workaround. See: https://github.com/dotnet/runtime/issues/55623
+ var color = default(TPixel);
+ color.FromVector4(TiffUtils.Vector4Default);
+ byte[] buffer = new byte[4];
+ int bufferStartIdx = this.isBigEndian ? 1 : 0;
+
+ Span redData = data[0].GetSpan();
+ Span greenData = data[1].GetSpan();
+ Span blueData = data[2].GetSpan();
+ Span alphaData = data[3].GetSpan();
+ Span bufferSpan = buffer.AsSpan(bufferStartIdx);
+
+ int offset = 0;
+ for (int y = top; y < top + height; y++)
+ {
+ Span pixelRow = pixels.DangerousGetRowSpan(y).Slice(left, width);
+ if (this.isBigEndian)
+ {
+ for (int x = 0; x < pixelRow.Length; x++)
+ {
+ redData.Slice(offset, 3).CopyTo(bufferSpan);
+ ulong r = TiffUtils.ConvertToUIntBigEndian(buffer);
+ greenData.Slice(offset, 3).CopyTo(bufferSpan);
+ ulong g = TiffUtils.ConvertToUIntBigEndian(buffer);
+ blueData.Slice(offset, 3).CopyTo(bufferSpan);
+ ulong b = TiffUtils.ConvertToUIntBigEndian(buffer);
+ alphaData.Slice(offset, 3).CopyTo(bufferSpan);
+ ulong a = TiffUtils.ConvertToUIntBigEndian(buffer);
+
+ offset += 3;
+
+ pixelRow[x] = TiffUtils.ColorScaleTo32Bit(r, g, b, a, color);
+ }
+ }
+ else
+ {
+ for (int x = 0; x < pixelRow.Length; x++)
+ {
+ redData.Slice(offset, 3).CopyTo(bufferSpan);
+ ulong r = TiffUtils.ConvertToUIntLittleEndian(buffer);
+ greenData.Slice(offset, 3).CopyTo(bufferSpan);
+ ulong g = TiffUtils.ConvertToUIntLittleEndian(buffer);
+ blueData.Slice(offset, 3).CopyTo(bufferSpan);
+ ulong b = TiffUtils.ConvertToUIntLittleEndian(buffer);
+ alphaData.Slice(offset, 3).CopyTo(bufferSpan);
+ ulong a = TiffUtils.ConvertToUIntLittleEndian(buffer);
+
+ offset += 3;
+
+ pixelRow[x] = TiffUtils.ColorScaleTo32Bit(r, g, b, a, color);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgba32PlanarTiffColor{TPixel}.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgba32PlanarTiffColor{TPixel}.cs
new file mode 100644
index 0000000000..e231111590
--- /dev/null
+++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgba32PlanarTiffColor{TPixel}.cs
@@ -0,0 +1,74 @@
+// Copyright (c) Six Labors.
+// Licensed under the Apache License, Version 2.0.
+
+using System;
+using System.Buffers;
+using SixLabors.ImageSharp.Formats.Tiff.Utils;
+using SixLabors.ImageSharp.Memory;
+using SixLabors.ImageSharp.PixelFormats;
+
+namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation
+{
+ ///
+ /// Implements the 'RGB' photometric interpretation with an alpha channel and a 'Planar' layout for each color channel with 32 bit.
+ ///
+ internal class Rgba32PlanarTiffColor : TiffBasePlanarColorDecoder
+ where TPixel : unmanaged, IPixel
+ {
+ private readonly bool isBigEndian;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// if set to true decodes the pixel data as big endian, otherwise as little endian.
+ public Rgba32PlanarTiffColor(bool isBigEndian) => this.isBigEndian = isBigEndian;
+
+ ///
+ public override void Decode(IMemoryOwner[] data, Buffer2D pixels, int left, int top, int width, int height)
+ {
+ // Note: due to an issue with netcore 2.1 and default values and unpredictable behavior with those,
+ // we define our own defaults as a workaround. See: https://github.com/dotnet/runtime/issues/55623
+ var color = default(TPixel);
+ color.FromVector4(TiffUtils.Vector4Default);
+
+ Span redData = data[0].GetSpan();
+ Span greenData = data[1].GetSpan();
+ Span blueData = data[2].GetSpan();
+ Span alphaData = data[3].GetSpan();
+
+ int offset = 0;
+ for (int y = top; y < top + height; y++)
+ {
+ Span pixelRow = pixels.DangerousGetRowSpan(y).Slice(left, width);
+ if (this.isBigEndian)
+ {
+ for (int x = 0; x < pixelRow.Length; x++)
+ {
+ ulong r = TiffUtils.ConvertToUIntBigEndian(redData.Slice(offset, 4));
+ ulong g = TiffUtils.ConvertToUIntBigEndian(greenData.Slice(offset, 4));
+ ulong b = TiffUtils.ConvertToUIntBigEndian(blueData.Slice(offset, 4));
+ ulong a = TiffUtils.ConvertToUIntBigEndian(alphaData.Slice(offset, 4));
+
+ offset += 4;
+
+ pixelRow[x] = TiffUtils.ColorScaleTo32Bit(r, g, b, a, color);
+ }
+ }
+ else
+ {
+ for (int x = 0; x < pixelRow.Length; x++)
+ {
+ ulong r = TiffUtils.ConvertToUIntLittleEndian(redData.Slice(offset, 4));
+ ulong g = TiffUtils.ConvertToUIntLittleEndian(greenData.Slice(offset, 4));
+ ulong b = TiffUtils.ConvertToUIntLittleEndian(blueData.Slice(offset, 4));
+ ulong a = TiffUtils.ConvertToUIntLittleEndian(alphaData.Slice(offset, 4));
+
+ offset += 4;
+
+ pixelRow[x] = TiffUtils.ColorScaleTo32Bit(r, g, b, a, color);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/RgbaPlanarTiffColor{TPixel}.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/RgbaPlanarTiffColor{TPixel}.cs
new file mode 100644
index 0000000000..f2ccf2ec81
--- /dev/null
+++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/RgbaPlanarTiffColor{TPixel}.cs
@@ -0,0 +1,87 @@
+// Copyright (c) Six Labors.
+// Licensed under the Apache License, Version 2.0.
+
+using System;
+using System.Buffers;
+using System.Numerics;
+using SixLabors.ImageSharp.Formats.Tiff.Utils;
+using SixLabors.ImageSharp.Memory;
+using SixLabors.ImageSharp.PixelFormats;
+
+namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation
+{
+ ///
+ /// Implements the 'RGB' photometric interpretation with an alpha channel and with 'Planar' layout (for all bit depths).
+ ///
+ internal class RgbaPlanarTiffColor : TiffBasePlanarColorDecoder
+ where TPixel : unmanaged, IPixel
+ {
+ private readonly float rFactor;
+
+ private readonly float gFactor;
+
+ private readonly float bFactor;
+
+ private readonly float aFactor;
+
+ private readonly ushort bitsPerSampleR;
+
+ private readonly ushort bitsPerSampleG;
+
+ private readonly ushort bitsPerSampleB;
+
+ private readonly ushort bitsPerSampleA;
+
+ public RgbaPlanarTiffColor(TiffBitsPerSample bitsPerSample)
+ {
+ this.bitsPerSampleR = bitsPerSample.Channel0;
+ this.bitsPerSampleG = bitsPerSample.Channel1;
+ this.bitsPerSampleB = bitsPerSample.Channel2;
+ this.bitsPerSampleA = bitsPerSample.Channel3;
+
+ this.rFactor = (1 << this.bitsPerSampleR) - 1.0f;
+ this.gFactor = (1 << this.bitsPerSampleG) - 1.0f;
+ this.bFactor = (1 << this.bitsPerSampleB) - 1.0f;
+ this.aFactor = (1 << this.bitsPerSampleA) - 1.0f;
+ }
+
+ ///
+ /// Decodes pixel data using the current photometric interpretation.
+ ///
+ /// The buffers to read image data from.
+ /// The image buffer to write pixels to.
+ /// The x-coordinate of the left-hand side of the image block.
+ /// The y-coordinate of the top of the image block.
+ /// The width of the image block.
+ /// The height of the image block.
+ public override void Decode(IMemoryOwner[] data, Buffer2D pixels, int left, int top, int width, int height)
+ {
+ var color = default(TPixel);
+
+ var rBitReader = new BitReader(data[0].GetSpan());
+ var gBitReader = new BitReader(data[1].GetSpan());
+ var bBitReader = new BitReader(data[2].GetSpan());
+ var aBitReader = new BitReader(data[3].GetSpan());
+
+ for (int y = top; y < top + height; y++)
+ {
+ Span pixelRow = pixels.DangerousGetRowSpan(y).Slice(left, width);
+ for (int x = 0; x < pixelRow.Length; x++)
+ {
+ float r = rBitReader.ReadBits(this.bitsPerSampleR) / this.rFactor;
+ float g = gBitReader.ReadBits(this.bitsPerSampleG) / this.gFactor;
+ float b = bBitReader.ReadBits(this.bitsPerSampleB) / this.bFactor;
+ float a = aBitReader.ReadBits(this.bitsPerSampleA) / this.aFactor;
+
+ color.FromVector4(new Vector4(r, g, b, a));
+ pixelRow[x] = color;
+ }
+
+ rBitReader.NextRow();
+ gBitReader.NextRow();
+ bBitReader.NextRow();
+ aBitReader.NextRow();
+ }
+ }
+ }
+}
diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorDecoderFactory{TPixel}.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorDecoderFactory{TPixel}.cs
index 25ca534315..1c608e3033 100644
--- a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorDecoderFactory{TPixel}.cs
+++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorDecoderFactory{TPixel}.cs
@@ -406,6 +406,10 @@ namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation
DebugGuard.IsTrue(colorMap == null, "colorMap");
return new RgbPlanarTiffColor(bitsPerSample);
+ case TiffColorType.Rgba8888Planar:
+ DebugGuard.IsTrue(colorMap == null, "colorMap");
+ return new RgbaPlanarTiffColor(bitsPerSample);
+
case TiffColorType.YCbCrPlanar:
return new YCbCrPlanarTiffColor(referenceBlackAndWhite, ycbcrCoefficients, ycbcrSubSampling);
@@ -413,14 +417,26 @@ namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation
DebugGuard.IsTrue(colorMap == null, "colorMap");
return new Rgb16PlanarTiffColor(byteOrder == ByteOrder.BigEndian);
+ case TiffColorType.Rgba16161616Planar:
+ DebugGuard.IsTrue(colorMap == null, "colorMap");
+ return new Rgba16PlanarTiffColor(byteOrder == ByteOrder.BigEndian);
+
case TiffColorType.Rgb242424Planar:
DebugGuard.IsTrue(colorMap == null, "colorMap");
return new Rgb24PlanarTiffColor(byteOrder == ByteOrder.BigEndian);
+ case TiffColorType.Rgba24242424Planar:
+ DebugGuard.IsTrue(colorMap == null, "colorMap");
+ return new Rgba24PlanarTiffColor(byteOrder == ByteOrder.BigEndian);
+
case TiffColorType.Rgb323232Planar:
DebugGuard.IsTrue(colorMap == null, "colorMap");
return new Rgb32PlanarTiffColor(byteOrder == ByteOrder.BigEndian);
+ case TiffColorType.Rgba32323232Planar:
+ DebugGuard.IsTrue(colorMap == null, "colorMap");
+ return new Rgba32PlanarTiffColor(byteOrder == ByteOrder.BigEndian);
+
default:
throw TiffThrowHelper.InvalidColorType(colorType.ToString());
}
diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorType.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorType.cs
index a0a48c2b93..6b39224fbd 100644
--- a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorType.cs
+++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorType.cs
@@ -233,21 +233,41 @@ namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation
///
Rgb888Planar,
+ ///
+ /// RGBA color image with an alpha channel. Planar configuration of data. 8 Bit per color channel.
+ ///
+ Rgba8888Planar,
+
///
/// RGB Full Color. Planar configuration of data. 16 Bit per color channel.
///
Rgb161616Planar,
+ ///
+ /// RGB Color with an alpha channel. Planar configuration of data. 16 Bit per color channel.
+ ///
+ Rgba16161616Planar,
+
///
/// RGB Full Color. Planar configuration of data. 24 Bit per color channel.
///
Rgb242424Planar,
+ ///
+ /// RGB Color with an alpha channel. Planar configuration of data. 24 Bit per color channel.
+ ///
+ Rgba24242424Planar,
+
///
/// RGB Full Color. Planar configuration of data. 32 Bit per color channel.
///
Rgb323232Planar,
+ ///
+ /// RGB Color with an alpha channel. Planar configuration of data. 32 Bit per color channel.
+ ///
+ Rgba32323232Planar,
+
///
/// The pixels are stored in YCbCr format.
///
diff --git a/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs b/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs
index aaaef0b8a7..e5b810738a 100644
--- a/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs
+++ b/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs
@@ -280,12 +280,10 @@ namespace SixLabors.ImageSharp.Formats.Tiff
return memory;
}
- else
- {
- DebugGuard.IsTrue(array is ulong[], $"Expected {nameof(UInt64)} array.");
- span = (ulong[])array;
- return null;
- }
+
+ DebugGuard.IsTrue(array is ulong[], $"Expected {nameof(UInt64)} array.");
+ span = (ulong[])array;
+ return null;
}
///
@@ -319,8 +317,11 @@ namespace SixLabors.ImageSharp.Formats.Tiff
case 2:
bitsPerPixel = this.BitsPerSample.Channel2;
break;
+ case 3:
+ bitsPerPixel = this.BitsPerSample.Channel2;
+ break;
default:
- TiffThrowHelper.ThrowNotSupported("More then 3 color channels are not supported");
+ TiffThrowHelper.ThrowNotSupported("More then 4 color channels are not supported");
break;
}
}
diff --git a/src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs b/src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs
index 0f1ffc79ff..23bc5f15f2 100644
--- a/src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs
+++ b/src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs
@@ -339,16 +339,16 @@ namespace SixLabors.ImageSharp.Formats.Tiff
switch (bitsPerChannel)
{
case 32:
- options.ColorType = TiffColorType.Rgb323232Planar;
+ options.ColorType = options.BitsPerSample.Channels is 3 ? TiffColorType.Rgb323232Planar : TiffColorType.Rgba32323232Planar;
break;
case 24:
- options.ColorType = TiffColorType.Rgb242424Planar;
+ options.ColorType = options.BitsPerSample.Channels is 3 ? TiffColorType.Rgb242424Planar : TiffColorType.Rgba24242424Planar;
break;
case 16:
- options.ColorType = TiffColorType.Rgb161616Planar;
+ options.ColorType = options.BitsPerSample.Channels is 3 ? TiffColorType.Rgb161616Planar : TiffColorType.Rgba16161616Planar;
break;
default:
- options.ColorType = TiffColorType.Rgb888Planar;
+ options.ColorType = options.BitsPerSample.Channels is 3 ? TiffColorType.Rgb888Planar : TiffColorType.Rgba8888Planar;
break;
}
}
diff --git a/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs
index de8ae8e729..18e39d44a5 100644
--- a/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs
@@ -78,9 +78,42 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
[Theory]
[WithFile(FlowerRgb888Planar6Strips, PixelTypes.Rgba32)]
[WithFile(FlowerRgb888Planar15Strips, PixelTypes.Rgba32)]
- public void TiffDecoder_Planar(TestImageProvider provider)
+ public void TiffDecoder_CanDecode_Planar(TestImageProvider provider)
where TPixel : unmanaged, IPixel => TestTiffDecoder(provider);
+ [Theory]
+ [WithFile(Rgba8BitPlanarUnassociatedAlpha, PixelTypes.Rgba32)]
+ public void TiffDecoder_CanDecode_Planar_32Bit(TestImageProvider provider)
+ where TPixel : unmanaged, IPixel => TestTiffDecoder(provider);
+
+ [Theory]
+ [WithFile(Rgba16BitPlanarUnassociatedAlphaLittleEndian, PixelTypes.Rgba32)]
+ [WithFile(Rgba16BitPlanarUnassociatedAlphaBigEndian, PixelTypes.Rgba32)]
+ public void TiffDecoder_CanDecode_Planar_64Bit(TestImageProvider provider)
+ where TPixel : unmanaged, IPixel => TestTiffDecoder(provider);
+
+ [Theory]
+ [WithFile(Rgba24BitPlanarUnassociatedAlphaLittleEndian, PixelTypes.Rgba32)]
+ [WithFile(Rgba24BitPlanarUnassociatedAlphaBigEndian, PixelTypes.Rgba32)]
+ public void TiffDecoder_CanDecode_Planar_96Bit(TestImageProvider provider)
+ where TPixel : unmanaged, IPixel
+ {
+ // Note: because the MagickReferenceDecoder fails to load the image, we only debug save them.
+ using Image image = provider.GetImage();
+ image.DebugSave(provider);
+ }
+
+ [Theory]
+ [WithFile(Rgba32BitPlanarUnassociatedAlphaLittleEndian, PixelTypes.Rgba32)]
+ [WithFile(Rgba32BitPlanarUnassociatedAlphaBigEndian, PixelTypes.Rgba32)]
+ public void TiffDecoder_CanDecode_Planar_128Bit(TestImageProvider provider)
+ where TPixel : unmanaged, IPixel
+ {
+ // Note: because the MagickReferenceDecoder fails to load the image, we only debug save them.
+ using Image image = provider.GetImage();
+ image.DebugSave(provider);
+ }
+
[Theory]
[WithFile(Calliphora_PaletteUncompressed, PixelTypes.Rgba32)]
[WithFile(PaletteDeflateMultistrip, PixelTypes.Rgba32)]
diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs
index 476d54e83f..9d37a0de47 100644
--- a/tests/ImageSharp.Tests/TestImages.cs
+++ b/tests/ImageSharp.Tests/TestImages.cs
@@ -865,18 +865,25 @@ namespace SixLabors.ImageSharp.Tests
public const string Rgba5BitUnassociatedAlpha = "Tiff/RgbaUnassociatedAlpha5bit.tiff";
public const string Rgba6BitUnassociatedAlpha = "Tiff/RgbaUnassociatedAlpha6bit.tiff";
public const string Rgba8BitUnassociatedAlpha = "Tiff/RgbaUnassociatedAlpha8bit.tiff";
+ public const string Rgba8BitPlanarUnassociatedAlpha = "Tiff/RgbaUnassociatedAlphaPlanar8bit.tiff";
public const string Rgba10BitUnassociatedAlphaBigEndian = "Tiff/RgbaUnassociatedAlpha10bit_msb.tiff";
- public const string Rgba10BitUnassociatedAlphaLittleEndian = "Tiff/RgbaUnassociatedAlpha10bit_msb.tiff";
+ public const string Rgba10BitUnassociatedAlphaLittleEndian = "Tiff/RgbaUnassociatedAlpha10bit_lsb.tiff";
public const string Rgba12BitUnassociatedAlphaBigEndian = "Tiff/RgbaUnassociatedAlpha12bit_msb.tiff";
- public const string Rgba12BitUnassociatedAlphaLittleEndian = "Tiff/RgbaUnassociatedAlpha12bit_msb.tiff";
+ public const string Rgba12BitUnassociatedAlphaLittleEndian = "Tiff/RgbaUnassociatedAlpha12bit_lsb.tiff";
public const string Rgba14BitUnassociatedAlphaBigEndian = "Tiff/RgbaUnassociatedAlpha14bit_msb.tiff";
- public const string Rgba14BitUnassociatedAlphaLittleEndian = "Tiff/RgbaUnassociatedAlpha14bit_msb.tiff";
+ public const string Rgba14BitUnassociatedAlphaLittleEndian = "Tiff/RgbaUnassociatedAlpha14bit_lsb.tiff";
public const string Rgba16BitUnassociatedAlphaBigEndian = "Tiff/RgbaUnassociatedAlpha16bit_msb.tiff";
- public const string Rgba16BitUnassociatedAlphaLittleEndian = "Tiff/RgbaUnassociatedAlpha16bit_msb.tiff";
+ public const string Rgba16BitUnassociatedAlphaLittleEndian = "Tiff/RgbaUnassociatedAlpha16bit_lsb.tiff";
+ public const string Rgba16BitPlanarUnassociatedAlphaBigEndian = "Tiff/RgbaUnassociatedAlphaPlanar16bit_msb.tiff";
+ public const string Rgba16BitPlanarUnassociatedAlphaLittleEndian = "Tiff/RgbaUnassociatedAlphaPlanar16bit_lsb.tiff";
public const string Rgba24BitUnassociatedAlphaBigEndian = "Tiff/RgbaUnassociatedAlpha24bit_msb.tiff";
- public const string Rgba24BitUnassociatedAlphaLittleEndian = "Tiff/RgbaUnassociatedAlpha24bit_msb.tiff";
+ public const string Rgba24BitUnassociatedAlphaLittleEndian = "Tiff/RgbaUnassociatedAlpha24bit_lsb.tiff";
+ public const string Rgba24BitPlanarUnassociatedAlphaBigEndian = "Tiff/RgbaUnassociatedAlphaPlanar24bit_msb.tiff";
+ public const string Rgba24BitPlanarUnassociatedAlphaLittleEndian = "Tiff/RgbaUnassociatedAlphaPlanar24bit_lsb.tiff";
public const string Rgba32BitUnassociatedAlphaBigEndian = "Tiff/RgbaUnassociatedAlpha32bit_msb.tiff";
- public const string Rgba32BitUnassociatedAlphaLittleEndian = "Tiff/RgbaUnassociatedAlpha32bit_msb.tiff";
+ public const string Rgba32BitUnassociatedAlphaLittleEndian = "Tiff/RgbaUnassociatedAlpha32bit_lsb.tiff";
+ public const string Rgba32BitPlanarUnassociatedAlphaBigEndian = "Tiff/RgbaUnassociatedAlphaPlanar32bit_msb.tiff";
+ public const string Rgba32BitPlanarUnassociatedAlphaLittleEndian = "Tiff/RgbaUnassociatedAlphaPlanar32bit_lsb.tiff";
public const string Issues1716Rgb161616BitLittleEndian = "Tiff/Issues/Issue1716.tiff";
public const string Issues1891 = "Tiff/Issues/Issue1891.tiff";
diff --git a/tests/Images/Input/Tiff/RgbaUnassociatedAlphaPlanar16bit_lsb.tiff b/tests/Images/Input/Tiff/RgbaUnassociatedAlphaPlanar16bit_lsb.tiff
new file mode 100644
index 0000000000..a24d74c19d
--- /dev/null
+++ b/tests/Images/Input/Tiff/RgbaUnassociatedAlphaPlanar16bit_lsb.tiff
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:6bc4325ce7be8a16d23c559300c79c3228c2f5a4c266844ba49763a32d29f10e
+size 470710
diff --git a/tests/Images/Input/Tiff/RgbaUnassociatedAlphaPlanar16bit_msb.tiff b/tests/Images/Input/Tiff/RgbaUnassociatedAlphaPlanar16bit_msb.tiff
new file mode 100644
index 0000000000..b7393cb227
--- /dev/null
+++ b/tests/Images/Input/Tiff/RgbaUnassociatedAlphaPlanar16bit_msb.tiff
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:08f8c284f7a9a6f362c09a418d85a94a1fe09bfc3f4cfe6859a82d6814718091
+size 470710
diff --git a/tests/Images/Input/Tiff/RgbaUnassociatedAlphaPlanar24bit_lsb.tiff b/tests/Images/Input/Tiff/RgbaUnassociatedAlphaPlanar24bit_lsb.tiff
new file mode 100644
index 0000000000..fd4171158f
--- /dev/null
+++ b/tests/Images/Input/Tiff/RgbaUnassociatedAlphaPlanar24bit_lsb.tiff
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:8ba4da7d63931f4462113e00bdee9e66e333ca42a47a33f62057c248bf4696ef
+size 705910
diff --git a/tests/Images/Input/Tiff/RgbaUnassociatedAlphaPlanar24bit_msb.tiff b/tests/Images/Input/Tiff/RgbaUnassociatedAlphaPlanar24bit_msb.tiff
new file mode 100644
index 0000000000..7aa6beeaaf
--- /dev/null
+++ b/tests/Images/Input/Tiff/RgbaUnassociatedAlphaPlanar24bit_msb.tiff
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:862ec9153cc755aa3ece8965a9d001a630ff756dfb018a9474661730482964cb
+size 705910
diff --git a/tests/Images/Input/Tiff/RgbaUnassociatedAlphaPlanar32bit_lsb.tiff b/tests/Images/Input/Tiff/RgbaUnassociatedAlphaPlanar32bit_lsb.tiff
new file mode 100644
index 0000000000..fb5dd1dccb
--- /dev/null
+++ b/tests/Images/Input/Tiff/RgbaUnassociatedAlphaPlanar32bit_lsb.tiff
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:dc4f67dacd3262418769831aeabf99c9a88a9674fabf9a08c8b3d3e47ac6d07a
+size 941110
diff --git a/tests/Images/Input/Tiff/RgbaUnassociatedAlphaPlanar32bit_msb.tiff b/tests/Images/Input/Tiff/RgbaUnassociatedAlphaPlanar32bit_msb.tiff
new file mode 100644
index 0000000000..6c45e96fa6
--- /dev/null
+++ b/tests/Images/Input/Tiff/RgbaUnassociatedAlphaPlanar32bit_msb.tiff
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:a98a0176f5db7af5b22c74f4a518c2df1055b5ca7e732f63426b3df8090fc313
+size 941110
diff --git a/tests/Images/Input/Tiff/RgbaUnassociatedAlphaPlanar8bit.tiff b/tests/Images/Input/Tiff/RgbaUnassociatedAlphaPlanar8bit.tiff
new file mode 100644
index 0000000000..f853cbc623
--- /dev/null
+++ b/tests/Images/Input/Tiff/RgbaUnassociatedAlphaPlanar8bit.tiff
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:2185ef9a84701bcff104d4f2fe40171ed853e5d02a2049b209ee2a4c65105ea9
+size 235502