diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZero32FloatTiffColor{TPixel}.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZero32FloatTiffColor{TPixel}.cs new file mode 100644 index 0000000000..ff34a29eb2 --- /dev/null +++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZero32FloatTiffColor{TPixel}.cs @@ -0,0 +1,69 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +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 'BlackIsZero' photometric interpretation for 32-bit float grayscale images. + /// + internal class BlackIsZero32FloatTiffColor : TiffBaseColorDecoder + 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 BlackIsZero32FloatTiffColor(bool isBigEndian) => this.isBigEndian = isBigEndian; + + /// + public override void Decode(ReadOnlySpan 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 offset = 0; + for (int y = top; y < top + height; y++) + { + Span pixelRow = pixels.GetRowSpan(y).Slice(left, width); + if (this.isBigEndian) + { + for (int x = 0; x < pixelRow.Length; x++) + { + data.Slice(offset, 4).CopyTo(buffer); + Array.Reverse(buffer); + float intensity = BitConverter.ToSingle(buffer, 0); + offset += 4; + + var colorVector = new Vector4(intensity, intensity, intensity, 1.0f); + color.FromVector4(colorVector); + pixelRow[x] = color; + } + } + else + { + for (int x = 0; x < pixelRow.Length; x++) + { + data.Slice(offset, 4).CopyTo(buffer); + float intensity = BitConverter.ToSingle(buffer, 0); + offset += 4; + + var colorVector = new Vector4(intensity, intensity, intensity, 1.0f); + color.FromVector4(colorVector); + pixelRow[x] = color; + } + } + } + } + } +} diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZero32TiffColor{TPixel}.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZero32TiffColor{TPixel}.cs index 862756bc42..f54a794840 100644 --- a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZero32TiffColor{TPixel}.cs +++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZero32TiffColor{TPixel}.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. using System; -using System.Numerics; using SixLabors.ImageSharp.Formats.Tiff.Utils; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/RgbFloat323232TiffColor{TPixel}.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/RgbFloat323232TiffColor{TPixel}.cs new file mode 100644 index 0000000000..f3f27d5c4b --- /dev/null +++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/RgbFloat323232TiffColor{TPixel}.cs @@ -0,0 +1,88 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +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 32 bits for each channel. + /// + internal class RgbFloat323232TiffColor : TiffBaseColorDecoder + 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 RgbFloat323232TiffColor(bool isBigEndian) => this.isBigEndian = isBigEndian; + + /// + public override void Decode(ReadOnlySpan 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); + int offset = 0; + byte[] buffer = new byte[4]; + + for (int y = top; y < top + height; y++) + { + Span pixelRow = pixels.GetRowSpan(y).Slice(left, width); + + if (this.isBigEndian) + { + for (int x = 0; x < pixelRow.Length; x++) + { + data.Slice(offset, 4).CopyTo(buffer); + Array.Reverse(buffer); + float r = BitConverter.ToSingle(buffer, 0); + offset += 4; + + data.Slice(offset, 4).CopyTo(buffer); + Array.Reverse(buffer); + float g = BitConverter.ToSingle(buffer, 0); + offset += 4; + + data.Slice(offset, 4).CopyTo(buffer); + Array.Reverse(buffer); + float b = BitConverter.ToSingle(buffer, 0); + offset += 4; + + var colorVector = new Vector4(r, g, b, 1.0f); + color.FromVector4(colorVector); + pixelRow[x] = color; + } + } + else + { + for (int x = 0; x < pixelRow.Length; x++) + { + data.Slice(offset, 4).CopyTo(buffer); + float r = BitConverter.ToSingle(buffer, 0); + offset += 4; + + data.Slice(offset, 4).CopyTo(buffer); + float g = BitConverter.ToSingle(buffer, 0); + offset += 4; + + data.Slice(offset, 4).CopyTo(buffer); + float b = BitConverter.ToSingle(buffer, 0); + offset += 4; + + var colorVector = new Vector4(r, g, b, 1.0f); + color.FromVector4(colorVector); + pixelRow[x] = color; + } + } + } + } + } +} diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorDecoderFactory{TPixel}.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorDecoderFactory{TPixel}.cs index 4a2fe93fe4..e27c0a61cf 100644 --- a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorDecoderFactory{TPixel}.cs +++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorDecoderFactory{TPixel}.cs @@ -47,6 +47,11 @@ public static TiffBaseColorDecoder Create(Configuration configuration, T DebugGuard.IsTrue(colorMap == null, "colorMap"); return new WhiteIsZero32TiffColor(byteOrder == ByteOrder.BigEndian); + case TiffColorType.WhiteIsZero32Float: + DebugGuard.IsTrue(bitsPerSample.Channels == 1 && bitsPerSample.Channel0 == 32, "bitsPerSample"); + DebugGuard.IsTrue(colorMap == null, "colorMap"); + return new WhiteIsZero32FloatTiffColor(byteOrder == ByteOrder.BigEndian); + case TiffColorType.BlackIsZero: DebugGuard.IsTrue(bitsPerSample.Channels == 1, "bitsPerSample"); DebugGuard.IsTrue(colorMap == null, "colorMap"); @@ -82,6 +87,11 @@ public static TiffBaseColorDecoder Create(Configuration configuration, T DebugGuard.IsTrue(colorMap == null, "colorMap"); return new BlackIsZero32TiffColor(byteOrder == ByteOrder.BigEndian); + case TiffColorType.BlackIsZero32Float: + DebugGuard.IsTrue(bitsPerSample.Channels == 1 && bitsPerSample.Channel0 == 32, "bitsPerSample"); + DebugGuard.IsTrue(colorMap == null, "colorMap"); + return new BlackIsZero32FloatTiffColor(byteOrder == ByteOrder.BigEndian); + case TiffColorType.Rgb: DebugGuard.IsTrue(colorMap == null, "colorMap"); return new RgbTiffColor(bitsPerSample); @@ -176,6 +186,16 @@ public static TiffBaseColorDecoder Create(Configuration configuration, T DebugGuard.IsTrue(colorMap == null, "colorMap"); return new Rgb323232TiffColor(isBigEndian: byteOrder == ByteOrder.BigEndian); + case TiffColorType.RgbFloat323232: + DebugGuard.IsTrue( + bitsPerSample.Channels == 3 + && bitsPerSample.Channel2 == 32 + && bitsPerSample.Channel1 == 32 + && bitsPerSample.Channel0 == 32, + "bitsPerSample"); + DebugGuard.IsTrue(colorMap == null, "colorMap"); + return new RgbFloat323232TiffColor(isBigEndian: byteOrder == ByteOrder.BigEndian); + case TiffColorType.PaletteColor: DebugGuard.NotNull(colorMap, "colorMap"); return new PaletteTiffColor(bitsPerSample, colorMap); diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorType.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorType.cs index dc47dc8cd4..81db744a1e 100644 --- a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorType.cs +++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorType.cs @@ -43,6 +43,11 @@ internal enum TiffColorType /// BlackIsZero32, + /// + /// Grayscale: 0 is imaged as black. The maximum value is imaged as white. Pixel data is 32-bit float. + /// + BlackIsZero32Float, + /// /// Grayscale: 0 is imaged as white. The maximum value is imaged as black. /// @@ -78,6 +83,11 @@ internal enum TiffColorType /// WhiteIsZero32, + /// + /// Grayscale: 0 is imaged as black. The maximum value is imaged as white. Pixel data is 32-bit float. + /// + WhiteIsZero32Float, + /// /// Palette-color. /// @@ -133,6 +143,11 @@ internal enum TiffColorType /// Rgb323232, + /// + /// RGB color image with 32 bits floats for each channel. + /// + RgbFloat323232, + /// /// RGB Full Color. Planar configuration of data. 8 Bit per color channel. /// diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero24TiffColor{TPixel}.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero24TiffColor{TPixel}.cs index b1088732ba..10182f250f 100644 --- a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero24TiffColor{TPixel}.cs +++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero24TiffColor{TPixel}.cs @@ -31,6 +31,7 @@ public override void Decode(ReadOnlySpan data, Buffer2D pixels, in color.FromVector4(TiffUtils.Vector4Default); byte[] buffer = new byte[4]; int bufferStartIdx = this.isBigEndian ? 1 : 0; + const uint maxValue = 0xFFFFFF; Span bufferSpan = buffer.AsSpan(bufferStartIdx); int offset = 0; @@ -42,7 +43,7 @@ public override void Decode(ReadOnlySpan data, Buffer2D pixels, in for (int x = 0; x < pixelRow.Length; x++) { data.Slice(offset, 3).CopyTo(bufferSpan); - ulong intensity = TiffUtils.ConvertToUIntBigEndian(buffer); + ulong intensity = maxValue - TiffUtils.ConvertToUIntBigEndian(buffer); offset += 3; pixelRow[x] = TiffUtils.ColorScaleTo24Bit(intensity, color); @@ -53,7 +54,7 @@ public override void Decode(ReadOnlySpan data, Buffer2D pixels, in for (int x = 0; x < pixelRow.Length; x++) { data.Slice(offset, 3).CopyTo(bufferSpan); - ulong intensity = TiffUtils.ConvertToUIntLittleEndian(buffer); + ulong intensity = maxValue - TiffUtils.ConvertToUIntLittleEndian(buffer); offset += 3; pixelRow[x] = TiffUtils.ColorScaleTo24Bit(intensity, color); diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero32FloatTiffColor{TPixel}.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero32FloatTiffColor{TPixel}.cs new file mode 100644 index 0000000000..d532247fe3 --- /dev/null +++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero32FloatTiffColor{TPixel}.cs @@ -0,0 +1,69 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +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 'WhiteIsZero' photometric interpretation for 32-bit float grayscale images. + /// + internal class WhiteIsZero32FloatTiffColor : TiffBaseColorDecoder + 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 WhiteIsZero32FloatTiffColor(bool isBigEndian) => this.isBigEndian = isBigEndian; + + /// + public override void Decode(ReadOnlySpan 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 offset = 0; + for (int y = top; y < top + height; y++) + { + Span pixelRow = pixels.GetRowSpan(y).Slice(left, width); + if (this.isBigEndian) + { + for (int x = 0; x < pixelRow.Length; x++) + { + data.Slice(offset, 4).CopyTo(buffer); + Array.Reverse(buffer); + float intensity = 1.0f - BitConverter.ToSingle(buffer, 0); + offset += 4; + + var colorVector = new Vector4(intensity, intensity, intensity, 1.0f); + color.FromVector4(colorVector); + pixelRow[x] = color; + } + } + else + { + for (int x = 0; x < pixelRow.Length; x++) + { + data.Slice(offset, 4).CopyTo(buffer); + float intensity = 1.0f - BitConverter.ToSingle(buffer, 0); + offset += 4; + + var colorVector = new Vector4(intensity, intensity, intensity, 1.0f); + color.FromVector4(colorVector); + pixelRow[x] = color; + } + } + } + } + } +} diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero32TiffColor{TPixel}.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero32TiffColor{TPixel}.cs index 0071740036..ef62b4f441 100644 --- a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero32TiffColor{TPixel}.cs +++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero32TiffColor{TPixel}.cs @@ -29,6 +29,7 @@ public override void Decode(ReadOnlySpan data, Buffer2D pixels, in // we define our own defaults as a workaround. See: https://github.com/dotnet/runtime/issues/55623 var color = default(TPixel); color.FromVector4(TiffUtils.Vector4Default); + const uint maxValue = 0xFFFFFFFF; int offset = 0; for (int y = top; y < top + height; y++) @@ -38,7 +39,7 @@ public override void Decode(ReadOnlySpan data, Buffer2D pixels, in { for (int x = 0; x < pixelRow.Length; x++) { - ulong intensity = TiffUtils.ConvertToUIntBigEndian(data.Slice(offset, 4)); + ulong intensity = maxValue - TiffUtils.ConvertToUIntBigEndian(data.Slice(offset, 4)); offset += 4; pixelRow[x] = TiffUtils.ColorScaleTo32Bit(intensity, color); @@ -48,7 +49,7 @@ public override void Decode(ReadOnlySpan data, Buffer2D pixels, in { for (int x = 0; x < pixelRow.Length; x++) { - ulong intensity = TiffUtils.ConvertToUIntLittleEndian(data.Slice(offset, 4)); + ulong intensity = maxValue - TiffUtils.ConvertToUIntLittleEndian(data.Slice(offset, 4)); offset += 4; pixelRow[x] = TiffUtils.ColorScaleTo32Bit(intensity, color); diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero8TiffColor{TPixel}.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero8TiffColor{TPixel}.cs index 6a6c2af225..15ebed58f9 100644 --- a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero8TiffColor{TPixel}.cs +++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero8TiffColor{TPixel}.cs @@ -27,7 +27,7 @@ public override void Decode(ReadOnlySpan data, Buffer2D pixels, in Span pixelRow = pixels.GetRowSpan(y).Slice(left, width); for (int x = 0; x < pixelRow.Length; x++) { - byte intensity = (byte)(255 - data[offset++]); + byte intensity = (byte)(byte.MaxValue - data[offset++]); pixelRow[x] = TiffUtils.ColorFromL8(l8, intensity, color); } } diff --git a/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs b/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs index 8477ba2d20..065f9d72f2 100644 --- a/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs +++ b/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs @@ -100,6 +100,11 @@ public TiffDecoderCore(Configuration configuration, ITiffDecoderOptions options) /// public TiffPhotometricInterpretation PhotometricInterpretation { get; set; } + /// + /// Gets or sets the sample format. + /// + public TiffSampleFormat SampleFormat { get; set; } + /// /// Gets or sets the horizontal predictor. /// diff --git a/src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs b/src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs index f59a9fbbab..a493c44678 100644 --- a/src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs +++ b/src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs @@ -45,14 +45,16 @@ public static void VerifyAndParse(this TiffDecoderCore options, ExifProfile exif TiffThrowHelper.ThrowNotSupported("TIFF images with FloatingPoint horizontal predictor are not supported."); } - TiffSampleFormat[] sampleFormat = exifProfile.GetValue(ExifTag.SampleFormat)?.Value?.Select(a => (TiffSampleFormat)a).ToArray(); - if (sampleFormat != null) + TiffSampleFormat[] sampleFormats = exifProfile.GetValue(ExifTag.SampleFormat)?.Value?.Select(a => (TiffSampleFormat)a).ToArray(); + TiffSampleFormat? sampleFormat = null; + if (sampleFormats != null) { - foreach (TiffSampleFormat format in sampleFormat) + sampleFormat = sampleFormats[0]; + foreach (TiffSampleFormat format in sampleFormats) { - if (format != TiffSampleFormat.UnsignedInteger) + if (format != TiffSampleFormat.UnsignedInteger && format != TiffSampleFormat.Float) { - TiffThrowHelper.ThrowNotSupported("ImageSharp only supports the UnsignedInteger SampleFormat."); + TiffThrowHelper.ThrowNotSupported("ImageSharp only supports the UnsignedInteger and Float SampleFormat."); } } } @@ -67,6 +69,7 @@ public static void VerifyAndParse(this TiffDecoderCore options, ExifProfile exif options.PlanarConfiguration = (TiffPlanarConfiguration?)exifProfile.GetValue(ExifTag.PlanarConfiguration)?.Value ?? DefaultPlanarConfiguration; options.Predictor = frameMetadata.Predictor ?? TiffPredictor.None; options.PhotometricInterpretation = frameMetadata.PhotometricInterpretation ?? TiffPhotometricInterpretation.Rgb; + options.SampleFormat = sampleFormat ?? TiffSampleFormat.UnsignedInteger; options.BitsPerPixel = frameMetadata.BitsPerPixel != null ? (int)frameMetadata.BitsPerPixel.Value : (int)TiffBitsPerPixel.Bit24; options.BitsPerSample = frameMetadata.BitsPerSample ?? new TiffBitsPerSample(0, 0, 0); options.FillOrder = fillOrder; @@ -114,6 +117,12 @@ private static void ParseColorType(this TiffDecoderCore options, ExifProfile exi { case 32: { + if (options.SampleFormat == TiffSampleFormat.Float) + { + options.ColorType = TiffColorType.WhiteIsZero32Float; + return; + } + options.ColorType = TiffColorType.WhiteIsZero32; break; } @@ -175,6 +184,12 @@ private static void ParseColorType(this TiffDecoderCore options, ExifProfile exi { case 32: { + if (options.SampleFormat == TiffSampleFormat.Float) + { + options.ColorType = TiffColorType.BlackIsZero32Float; + return; + } + options.ColorType = TiffColorType.BlackIsZero32; break; } @@ -238,6 +253,12 @@ private static void ParseColorType(this TiffDecoderCore options, ExifProfile exi switch (bitsPerChannel) { case 32: + if (options.SampleFormat == TiffSampleFormat.Float) + { + options.ColorType = TiffColorType.RgbFloat323232; + return; + } + options.ColorType = TiffColorType.Rgb323232; break; diff --git a/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs index 77a8153c50..9494a853d3 100644 --- a/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs @@ -237,6 +237,30 @@ public void TiffDecoder_CanDecode_96Bit(TestImageProvider provid image.DebugSave(provider); } + [Theory] + [WithFile(FlowerRgbFloat323232, PixelTypes.Rgba32)] + [WithFile(FlowerRgbFloat323232LittleEndian, PixelTypes.Rgba32)] + public void TiffDecoder_CanDecode_Float_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(Flower32BitFloatGray, PixelTypes.Rgba32)] + [WithFile(Flower32BitFloatGrayLittleEndian, PixelTypes.Rgba32)] + [WithFile(Flower32BitFloatGrayMinIsWhite, PixelTypes.Rgba32)] + [WithFile(Flower32BitFloatGrayMinIsWhiteLittleEndian, PixelTypes.Rgba32)] + public void TiffDecoder_CanDecode_Float_96Bit_Gray(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(GrayscaleDeflateMultistrip, PixelTypes.Rgba32)] [WithFile(RgbDeflateMultistrip, PixelTypes.Rgba32)] diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 059e51cec9..8042f5e825 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -565,6 +565,8 @@ public static class Tiff public const string RgbPalette = "Tiff/rgb_palette.tiff"; public const string Rgb4BitPalette = "Tiff/bike_colorpalette_4bit.tiff"; public const string RgbPaletteDeflate = "Tiff/rgb_palette_deflate.tiff"; + public const string FlowerRgbFloat323232 = "Tiff/flower-rgb-float32_msb.tiff"; + public const string FlowerRgbFloat323232LittleEndian = "Tiff/flower-rgb-float32_lsb.tiff"; public const string FlowerRgb323232Contiguous = "Tiff/flower-rgb-contig-32.tiff"; public const string FlowerRgb323232ContiguousLittleEndian = "Tiff/flower-rgb-contig-32_lsb.tiff"; public const string FlowerRgb323232Planar = "Tiff/flower-rgb-planar-32.tiff"; @@ -600,12 +602,16 @@ public static class Tiff public const string Flower16BitGray = "Tiff/flower-minisblack-16.tiff"; public const string Flower16BitGrayLittleEndian = "Tiff/flower-minisblack-16_lsb.tiff"; public const string Flower16BitGrayMinIsWhiteLittleEndian = "Tiff/flower-miniswhite-16_lsb.tiff"; - public const string Flower16BitGrayMinIsWhiteBigEndian = "Tiff/flower-miniswhite-16.tiff"; - public const string Flower24BitGray = "Tiff/flower-minisblack-24.tiff"; + public const string Flower16BitGrayMinIsWhiteBigEndian = "Tiff/flower-miniswhite-16_msb.tiff"; + public const string Flower24BitGray = "Tiff/flower-minisblack-24_msb.tiff"; public const string Flower24BitGrayLittleEndian = "Tiff/flower-minisblack-24_lsb.tiff"; - public const string Flower32BitGray = "Tiff/flower-minisblack-32.tiff"; + public const string Flower32BitGray = "Tiff/flower-minisblack-32_msb.tiff"; public const string Flower32BitGrayLittleEndian = "Tiff/flower-minisblack-32_lsb.tiff"; - public const string Flower32BitGrayMinIsWhite = "Tiff/flower-miniswhite-32.tiff"; + public const string Flower32BitFloatGray = "Tiff/flower-minisblack-float32_msb.tiff"; + public const string Flower32BitFloatGrayLittleEndian = "Tiff/flower-minisblack-float32_lsb.tiff"; + public const string Flower32BitFloatGrayMinIsWhite = "Tiff/flower-miniswhite-float32_msb.tiff"; + public const string Flower32BitFloatGrayMinIsWhiteLittleEndian = "Tiff/flower-miniswhite-float32_lsb.tiff"; + public const string Flower32BitGrayMinIsWhite = "Tiff/flower-miniswhite-32_msb.tiff"; public const string Flower32BitGrayMinIsWhiteLittleEndian = "Tiff/flower-miniswhite-32_lsb.tiff"; public const string Issues1716Rgb161616BitLittleEndian = "Tiff/Issues/Issue1716.tiff"; diff --git a/tests/Images/Input/Tiff/flower-minisblack-24.tiff b/tests/Images/Input/Tiff/flower-minisblack-24_msb.tiff similarity index 100% rename from tests/Images/Input/Tiff/flower-minisblack-24.tiff rename to tests/Images/Input/Tiff/flower-minisblack-24_msb.tiff diff --git a/tests/Images/Input/Tiff/flower-minisblack-32.tiff b/tests/Images/Input/Tiff/flower-minisblack-32_msb.tiff similarity index 100% rename from tests/Images/Input/Tiff/flower-minisblack-32.tiff rename to tests/Images/Input/Tiff/flower-minisblack-32_msb.tiff diff --git a/tests/Images/Input/Tiff/flower-minisblack-float32_lsb.tiff b/tests/Images/Input/Tiff/flower-minisblack-float32_lsb.tiff new file mode 100644 index 0000000000..8e94faea0b --- /dev/null +++ b/tests/Images/Input/Tiff/flower-minisblack-float32_lsb.tiff @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:af82e07e6298082c91d60a97acb29b67ecabf386bc14371fcb698b248cfd3b40 +size 12814 diff --git a/tests/Images/Input/Tiff/flower-minisblack-float32_msb.tiff b/tests/Images/Input/Tiff/flower-minisblack-float32_msb.tiff new file mode 100644 index 0000000000..464074c153 --- /dev/null +++ b/tests/Images/Input/Tiff/flower-minisblack-float32_msb.tiff @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5c918b8aa9968c03c12d85b3bcacd35ae57663a19f5490fc1c351521ed835f30 +size 12814 diff --git a/tests/Images/Input/Tiff/flower-miniswhite-16.tiff b/tests/Images/Input/Tiff/flower-miniswhite-16_msb.tiff similarity index 100% rename from tests/Images/Input/Tiff/flower-miniswhite-16.tiff rename to tests/Images/Input/Tiff/flower-miniswhite-16_msb.tiff diff --git a/tests/Images/Input/Tiff/flower-miniswhite-32.tiff b/tests/Images/Input/Tiff/flower-miniswhite-32.tiff deleted file mode 100644 index f8cf87553e..0000000000 --- a/tests/Images/Input/Tiff/flower-miniswhite-32.tiff +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:514417ead3d6c5c6ca33374ef0bb6ecbe5f875a266519d4cbaa4a6b91033d243 -size 12778 diff --git a/tests/Images/Input/Tiff/flower-miniswhite-32_lsb.tiff b/tests/Images/Input/Tiff/flower-miniswhite-32_lsb.tiff index 8c99dda7fb..d44ae9b915 100644 --- a/tests/Images/Input/Tiff/flower-miniswhite-32_lsb.tiff +++ b/tests/Images/Input/Tiff/flower-miniswhite-32_lsb.tiff @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:64c948aa03bc4a24cd1d68bb18b5031c119936154a90f1cb1d9aaabd854c5d9b +oid sha256:17139bc00d9fe2905fbac9226120d2823ea17a10a39b140970122153ec23265d size 12778 diff --git a/tests/Images/Input/Tiff/flower-miniswhite-32_msb.tiff b/tests/Images/Input/Tiff/flower-miniswhite-32_msb.tiff new file mode 100644 index 0000000000..d44ae9b915 --- /dev/null +++ b/tests/Images/Input/Tiff/flower-miniswhite-32_msb.tiff @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:17139bc00d9fe2905fbac9226120d2823ea17a10a39b140970122153ec23265d +size 12778 diff --git a/tests/Images/Input/Tiff/flower-miniswhite-float32_lsb.tiff b/tests/Images/Input/Tiff/flower-miniswhite-float32_lsb.tiff new file mode 100644 index 0000000000..3241c8fbec --- /dev/null +++ b/tests/Images/Input/Tiff/flower-miniswhite-float32_lsb.tiff @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:93e06533486f15e33f2435d081713fbecc3ba96c842058b7ba3a5d9116fe5f5c +size 12814 diff --git a/tests/Images/Input/Tiff/flower-miniswhite-float32_msb.tiff b/tests/Images/Input/Tiff/flower-miniswhite-float32_msb.tiff new file mode 100644 index 0000000000..5623a74286 --- /dev/null +++ b/tests/Images/Input/Tiff/flower-miniswhite-float32_msb.tiff @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:800a101f4d23fa2a499fcef036ebfca7d9338ac71b06a32ad05e7eb1905ddae3 +size 12814 diff --git a/tests/Images/Input/Tiff/flower-rgb-float32_lsb.tiff b/tests/Images/Input/Tiff/flower-rgb-float32_lsb.tiff new file mode 100644 index 0000000000..da0f104387 --- /dev/null +++ b/tests/Images/Input/Tiff/flower-rgb-float32_lsb.tiff @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a1f889baa6f3bb99f15609848cdd47d548d3e2ed1b7b558d428550dfa3bd4bf9 +size 38050 diff --git a/tests/Images/Input/Tiff/flower-rgb-float32_msb.tiff b/tests/Images/Input/Tiff/flower-rgb-float32_msb.tiff new file mode 100644 index 0000000000..353771db94 --- /dev/null +++ b/tests/Images/Input/Tiff/flower-rgb-float32_msb.tiff @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2c02be5dff2bcd5d60afbf379ba9095b0c8fd3a7a0063f684ac9ac9119f967a5 +size 38050