From 42d5d9ee912f8d5d1b8307cc5d916fddc7a89387 Mon Sep 17 00:00:00 2001 From: Brian Popow Date: Thu, 3 Jun 2021 12:10:27 +0200 Subject: [PATCH] Add support for decoding 6 bit per pixel tiff's --- src/ImageSharp/Formats/Tiff/Constants/TiffConstants.cs | 9 +++++++-- .../TiffColorDecoderFactory{TPixel}.cs | 10 ++++++++++ .../Tiff/PhotometricInterpretation/TiffColorType.cs | 9 +++++++-- src/ImageSharp/Formats/Tiff/TiffBitsPerPixel.cs | 9 ++++++++- src/ImageSharp/Formats/Tiff/TiffBitsPerSample.cs | 5 +++++ .../Formats/Tiff/TiffBitsPerSampleExtensions.cs | 9 +++++++++ .../Formats/Tiff/TiffDecoderOptionsParser.cs | 4 ++++ src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs | 3 ++- .../ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs | 6 ++++++ .../ImageSharp.Tests/Formats/Tiff/TiffEncoderTests.cs | 1 + tests/ImageSharp.Tests/TestImages.cs | 2 ++ tests/Images/Input/Tiff/flower-rgb-contig-02.tiff | 3 +++ tests/Images/Input/Tiff/flower-rgb-planar-02.tiff | 3 +++ 13 files changed, 67 insertions(+), 6 deletions(-) create mode 100644 tests/Images/Input/Tiff/flower-rgb-contig-02.tiff create mode 100644 tests/Images/Input/Tiff/flower-rgb-planar-02.tiff diff --git a/src/ImageSharp/Formats/Tiff/Constants/TiffConstants.cs b/src/ImageSharp/Formats/Tiff/Constants/TiffConstants.cs index 988b1242ae..f56488a52f 100644 --- a/src/ImageSharp/Formats/Tiff/Constants/TiffConstants.cs +++ b/src/ImageSharp/Formats/Tiff/Constants/TiffConstants.cs @@ -96,15 +96,20 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Constants public static readonly ushort[] BitsPerSample8Bit = { 8 }; /// - /// The bits per sample for color images with 8 bits for each color channel. + /// The bits per sample for color images with 2 bits for each color channel. /// - public static readonly ushort[] BitsPerSampleRgb8Bit = { 8, 8, 8 }; + public static readonly ushort[] BitsPerSampleRgb2Bit = { 2, 2, 2 }; /// /// The bits per sample for color images with 4 bits for each color channel. /// public static readonly ushort[] BitsPerSampleRgb4Bit = { 4, 4, 4 }; + /// + /// The bits per sample for color images with 8 bits for each color channel. + /// + public static readonly ushort[] BitsPerSampleRgb8Bit = { 8, 8, 8 }; + /// /// The list of mimetypes that equate to a tiff. /// diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorDecoderFactory{TPixel}.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorDecoderFactory{TPixel}.cs index d78b06aa7f..2c59fdf137 100644 --- a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorDecoderFactory{TPixel}.cs +++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorDecoderFactory{TPixel}.cs @@ -57,6 +57,16 @@ namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation DebugGuard.IsTrue(colorMap == null, "colorMap"); return new RgbTiffColor(bitsPerSample); + case TiffColorType.Rgb222: + DebugGuard.IsTrue( + bitsPerSample.Length == 3 + && bitsPerSample[0] == 2 + && bitsPerSample[1] == 2 + && bitsPerSample[2] == 2, + "bitsPerSample"); + DebugGuard.IsTrue(colorMap == null, "colorMap"); + return new RgbTiffColor(bitsPerSample); + case TiffColorType.Rgb444: DebugGuard.IsTrue( bitsPerSample.Length == 3 diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorType.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorType.cs index 089dc31ade..1d6535fd71 100644 --- a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorType.cs +++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorType.cs @@ -59,15 +59,20 @@ namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation Rgb, /// - /// RGB Full Color. Optimized implementation for 8-bit images. + /// RGB color image with 2 bits for each channel. /// - Rgb888, + Rgb222, /// /// RGB color image with 4 bits for each channel. /// Rgb444, + /// + /// RGB Full Color. Optimized implementation for 8-bit images. + /// + Rgb888, + /// /// RGB Full Color. Planar configuration of data. /// diff --git a/src/ImageSharp/Formats/Tiff/TiffBitsPerPixel.cs b/src/ImageSharp/Formats/Tiff/TiffBitsPerPixel.cs index 4b65f88b8c..0dee1105bb 100644 --- a/src/ImageSharp/Formats/Tiff/TiffBitsPerPixel.cs +++ b/src/ImageSharp/Formats/Tiff/TiffBitsPerPixel.cs @@ -18,6 +18,13 @@ namespace SixLabors.ImageSharp.Formats.Tiff /// Bit4 = 4, + /// + /// 6 bits per pixel. 2 bit for each color channel. + /// + /// Note: The TiffEncoder does not yet support 2 bits per color channel and will default to 24 bits per pixel instead. + /// + Bit6 = 6, + /// /// 8 bits per pixel, grayscale or color palette images. /// @@ -26,7 +33,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff /// /// 12 bits per pixel. 4 bit for each color channel. /// - /// Note: The TiffEncoder does not yet support 4 bits per color channel and will default to 24 bits per pixel. + /// Note: The TiffEncoder does not yet support 4 bits per color channel and will default to 24 bits per pixel instead. /// Bit12 = 12, diff --git a/src/ImageSharp/Formats/Tiff/TiffBitsPerSample.cs b/src/ImageSharp/Formats/Tiff/TiffBitsPerSample.cs index 992a5ad6eb..0a4962b530 100644 --- a/src/ImageSharp/Formats/Tiff/TiffBitsPerSample.cs +++ b/src/ImageSharp/Formats/Tiff/TiffBitsPerSample.cs @@ -28,6 +28,11 @@ namespace SixLabors.ImageSharp.Formats.Tiff /// Bit8 = 8, + /// + /// Six bits per sample, each channel has 2 bits. + /// + Bit6 = 6, + /// /// Twelve bits per sample, each channel has 4 bits. /// diff --git a/src/ImageSharp/Formats/Tiff/TiffBitsPerSampleExtensions.cs b/src/ImageSharp/Formats/Tiff/TiffBitsPerSampleExtensions.cs index 0687b0104a..923e355f40 100644 --- a/src/ImageSharp/Formats/Tiff/TiffBitsPerSampleExtensions.cs +++ b/src/ImageSharp/Formats/Tiff/TiffBitsPerSampleExtensions.cs @@ -21,6 +21,8 @@ namespace SixLabors.ImageSharp.Formats.Tiff return TiffConstants.BitsPerSample1Bit; case TiffBitsPerSample.Bit4: return TiffConstants.BitsPerSample4Bit; + case TiffBitsPerSample.Bit6: + return TiffConstants.BitsPerSampleRgb2Bit; case TiffBitsPerSample.Bit8: return TiffConstants.BitsPerSample8Bit; case TiffBitsPerSample.Bit12: @@ -57,6 +59,13 @@ namespace SixLabors.ImageSharp.Formats.Tiff return TiffBitsPerSample.Bit12; } + if (bitsPerSample[2] == TiffConstants.BitsPerSampleRgb2Bit[2] && + bitsPerSample[1] == TiffConstants.BitsPerSampleRgb2Bit[1] && + bitsPerSample[0] == TiffConstants.BitsPerSampleRgb2Bit[0]) + { + return TiffBitsPerSample.Bit6; + } + break; case 1: diff --git a/src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs b/src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs index b38ff68c18..1c2ee2443d 100644 --- a/src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs +++ b/src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs @@ -188,6 +188,9 @@ namespace SixLabors.ImageSharp.Formats.Tiff case TiffBitsPerSample.Bit12: options.ColorType = TiffColorType.Rgb444; break; + case TiffBitsPerSample.Bit6: + options.ColorType = TiffColorType.Rgb222; + break; default: TiffThrowHelper.ThrowNotSupported("Bits per sample is not supported."); break; @@ -285,6 +288,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff { TiffBitsPerPixel.Bit1 => TiffBitsPerSample.Bit1, TiffBitsPerPixel.Bit4 => TiffBitsPerSample.Bit4, + TiffBitsPerPixel.Bit6 => TiffBitsPerSample.Bit6, TiffBitsPerPixel.Bit8 => TiffBitsPerSample.Bit8, TiffBitsPerPixel.Bit12 => TiffBitsPerSample.Bit12, TiffBitsPerPixel.Bit24 => TiffBitsPerSample.Bit24, diff --git a/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs b/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs index 6b5ca0086f..b61a0c0e1a 100644 --- a/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs +++ b/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs @@ -319,8 +319,9 @@ namespace SixLabors.ImageSharp.Formats.Tiff case TiffBitsPerPixel.Bit8: this.SetEncoderOptions(bitsPerPixel, photometricInterpretation ?? TiffPhotometricInterpretation.BlackIsZero, compression, predictor); break; + case TiffBitsPerPixel.Bit6: case TiffBitsPerPixel.Bit12: - // Encoding 12 bits per pixel is not yet supported. Default to 24 bits. + // Encoding 12 and 6 bits per pixel is not yet supported. Default to 24 bits. this.SetEncoderOptions(TiffBitsPerPixel.Bit24, TiffPhotometricInterpretation.Rgb, compression, TiffPredictor.None); break; default: diff --git a/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs index c58977813a..ad27ed0fcc 100644 --- a/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs @@ -99,6 +99,12 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff public void TiffDecoder_CanDecode_4Bit_WithPalette(TestImageProvider provider) where TPixel : unmanaged, IPixel => TestTiffDecoder(provider, ReferenceDecoder, useExactComparer: false, 0.01f); + [Theory] + [WithFile(FlowerRgb222Contiguous, PixelTypes.Rgba32)] + [WithFile(FlowerRgb222Planar, PixelTypes.Rgba32)] + public void TiffDecoder_CanDecode_6Bit(TestImageProvider provider) + where TPixel : unmanaged, IPixel => TestTiffDecoder(provider); + [Theory] [WithFile(FlowerRgb444Contiguous, PixelTypes.Rgba32)] [WithFile(FlowerRgb444Planar, PixelTypes.Rgba32)] diff --git a/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderTests.cs index dd3ef133e6..1b3104e728 100644 --- a/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderTests.cs @@ -79,6 +79,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff [Theory] [InlineData(TiffBitsPerPixel.Bit12)] + [InlineData(TiffBitsPerPixel.Bit6)] public void EncoderOptions_UnsupportedBitPerPixel_DefaultTo24Bits(TiffBitsPerPixel bitsPerPixel) { // arrange diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index d1c29489fb..3eff09c75f 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -562,6 +562,8 @@ namespace SixLabors.ImageSharp.Tests public const string Flower4BitPaletteGray = "Tiff/flower-minisblack-04.tiff"; public const string FlowerRgb444Contiguous = "Tiff/flower-rgb-contig-04.tiff"; public const string FlowerRgb444Planar = "Tiff/flower-rgb-planar-04.tiff"; + public const string FlowerRgb222Contiguous = "Tiff/flower-rgb-contig-02.tiff"; + public const string FlowerRgb222Planar = "Tiff/flower-rgb-planar-02.tiff"; public const string SmallRgbDeflate = "Tiff/rgb_small_deflate.tiff"; public const string SmallRgbLzw = "Tiff/rgb_small_lzw.tiff"; diff --git a/tests/Images/Input/Tiff/flower-rgb-contig-02.tiff b/tests/Images/Input/Tiff/flower-rgb-contig-02.tiff new file mode 100644 index 0000000000..a2d253dbd5 --- /dev/null +++ b/tests/Images/Input/Tiff/flower-rgb-contig-02.tiff @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fbcd225c0db343f0cc984c35609b81f6413ebc1ba2ce2494d3607db375e969ff +size 2685 diff --git a/tests/Images/Input/Tiff/flower-rgb-planar-02.tiff b/tests/Images/Input/Tiff/flower-rgb-planar-02.tiff new file mode 100644 index 0000000000..8b301a534d --- /dev/null +++ b/tests/Images/Input/Tiff/flower-rgb-planar-02.tiff @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:21c4ede6382d8c72cb8e6f7939203d5111b362646a9727d95a2f63310ec8e5b3 +size 2795