diff --git a/src/ImageSharp/Formats/Tiff/TiffBitsPerSample.cs b/src/ImageSharp/Formats/Tiff/TiffBitsPerSample.cs deleted file mode 100644 index 088ef5d6f8..0000000000 --- a/src/ImageSharp/Formats/Tiff/TiffBitsPerSample.cs +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -namespace SixLabors.ImageSharp.Formats.Tiff -{ - /// - /// The number of bits per component. - /// - public enum TiffBitsPerSample - { - /// - /// The Bits per samples is not known. - /// - Unknown = 0, - - /// - /// One bit per sample for bicolor images. - /// - Bit1 = 1, - - /// - /// Four bits per sample for grayscale images with 16 different levels of gray or paletted images with a palette of 16 colors. - /// - Bit4 = 4, - - /// - /// Eight bits per sample for grayscale images with 256 different levels of gray or paletted images with a palette of 256 colors. - /// - Bit8 = 8, - - /// - /// Six bits per sample, each channel has 2 bits. - /// - Bit6 = 6, - - /// - /// Twelve bits per sample, each channel has 4 bits. - /// - Bit12 = 12, - - /// - /// 24 bits per sample, each color channel has 8 Bits. - /// - Bit24 = 24, - - /// - /// Thirty bits per sample, each channel has 10 bits. - /// - Bit30 = 30, - - /// - /// Forty two bits per sample, each channel has 14 bits. - /// - Bit42 = 42, - } -} diff --git a/src/ImageSharp/Formats/Tiff/TiffBitsPerSampleExtensions.cs b/src/ImageSharp/Formats/Tiff/TiffBitsPerSampleExtensions.cs deleted file mode 100644 index ca0f0befcc..0000000000 --- a/src/ImageSharp/Formats/Tiff/TiffBitsPerSampleExtensions.cs +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -using System; -using SixLabors.ImageSharp.Formats.Tiff.Constants; - -namespace SixLabors.ImageSharp.Formats.Tiff -{ - internal static class TiffBitsPerSampleExtensions - { - /// - /// Gets the bits per channel array for a given BitsPerSample value, e,g, for RGB888: [8, 8, 8] - /// - /// The tiff bits per sample. - /// Bits per sample array. - public static ushort[] Bits(this TiffBitsPerSample tiffBitsPerSample) - { - switch (tiffBitsPerSample) - { - case TiffBitsPerSample.Bit1: - return TiffConstants.BitsPerSample1Bit; - case TiffBitsPerSample.Bit4: - return TiffConstants.BitsPerSample4Bit; - case TiffBitsPerSample.Bit6: - return TiffConstants.BitsPerSampleRgb2Bit; - case TiffBitsPerSample.Bit8: - return TiffConstants.BitsPerSample8Bit; - case TiffBitsPerSample.Bit12: - return TiffConstants.BitsPerSampleRgb4Bit; - case TiffBitsPerSample.Bit24: - return TiffConstants.BitsPerSampleRgb8Bit; - case TiffBitsPerSample.Bit30: - return TiffConstants.BitsPerSampleRgb10Bit; - case TiffBitsPerSample.Bit42: - return TiffConstants.BitsPerSampleRgb14Bit; - - default: - return Array.Empty(); - } - } - - /// - /// Maps an array of bits per sample to a concrete enum value. - /// - /// The bits per sample array. - /// TiffBitsPerSample enum value. - public static TiffBitsPerSample GetBitsPerSample(this ushort[] bitsPerSample) - { - switch (bitsPerSample.Length) - { - case 3: - if (bitsPerSample[2] == TiffConstants.BitsPerSampleRgb14Bit[2] && - bitsPerSample[1] == TiffConstants.BitsPerSampleRgb14Bit[1] && - bitsPerSample[0] == TiffConstants.BitsPerSampleRgb14Bit[0]) - { - return TiffBitsPerSample.Bit42; - } - - if (bitsPerSample[2] == TiffConstants.BitsPerSampleRgb10Bit[2] && - bitsPerSample[1] == TiffConstants.BitsPerSampleRgb10Bit[1] && - bitsPerSample[0] == TiffConstants.BitsPerSampleRgb10Bit[0]) - { - return TiffBitsPerSample.Bit30; - } - - if (bitsPerSample[2] == TiffConstants.BitsPerSampleRgb8Bit[2] && - bitsPerSample[1] == TiffConstants.BitsPerSampleRgb8Bit[1] && - bitsPerSample[0] == TiffConstants.BitsPerSampleRgb8Bit[0]) - { - return TiffBitsPerSample.Bit24; - } - - if (bitsPerSample[2] == TiffConstants.BitsPerSampleRgb4Bit[2] && - bitsPerSample[1] == TiffConstants.BitsPerSampleRgb4Bit[1] && - bitsPerSample[0] == TiffConstants.BitsPerSampleRgb4Bit[0]) - { - 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: - if (bitsPerSample[0] == TiffConstants.BitsPerSample1Bit[0]) - { - return TiffBitsPerSample.Bit1; - } - - if (bitsPerSample[0] == TiffConstants.BitsPerSample4Bit[0]) - { - return TiffBitsPerSample.Bit4; - } - - if (bitsPerSample[0] == TiffConstants.BitsPerSample8Bit[0]) - { - return TiffBitsPerSample.Bit8; - } - - break; - } - - return TiffBitsPerSample.Unknown; - } - } -} diff --git a/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs b/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs index fadb4f7c2e..294407ef97 100644 --- a/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs +++ b/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs @@ -50,9 +50,9 @@ namespace SixLabors.ImageSharp.Formats.Tiff } /// - /// Gets or sets the number of bits per component of the pixel format used to decode the image. + /// Gets or sets the bits per sample. /// - public TiffBitsPerSample BitsPerSample { get; set; } + public ushort[] BitsPerSample { get; set; } /// /// Gets or sets the bits per pixel. @@ -207,7 +207,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff } else { - bitsPerPixel = this.BitsPerSample.Bits()[plane]; + bitsPerPixel = this.BitsPerSample[plane]; } int bytesPerRow = ((width * bitsPerPixel) + 7) / 8; @@ -225,7 +225,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff private void DecodeStripsPlanar(ImageFrame frame, int rowsPerStrip, Number[] stripOffsets, Number[] stripByteCounts) where TPixel : unmanaged, IPixel { - int stripsPerPixel = this.BitsPerSample.Bits().Length; + int stripsPerPixel = this.BitsPerSample.Length; int stripsPerPlane = stripOffsets.Length / stripsPerPixel; int bitsPerPixel = this.BitsPerPixel; @@ -243,7 +243,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff using TiffBaseDecompressor decompressor = TiffDecompressorsFactory.Create(this.CompressionType, this.memoryAllocator, this.PhotometricInterpretation, frame.Width, bitsPerPixel, this.Predictor, this.FaxCompressionOptions); - RgbPlanarTiffColor colorDecoder = TiffColorDecoderFactory.CreatePlanar(this.ColorType, this.BitsPerSample.Bits(), this.ColorMap); + RgbPlanarTiffColor colorDecoder = TiffColorDecoderFactory.CreatePlanar(this.ColorType, this.BitsPerSample, this.ColorMap); for (int i = 0; i < stripsPerPlane; i++) { @@ -286,7 +286,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff using TiffBaseDecompressor decompressor = TiffDecompressorsFactory.Create(this.CompressionType, this.memoryAllocator, this.PhotometricInterpretation, frame.Width, bitsPerPixel, this.Predictor, this.FaxCompressionOptions); - TiffBaseColorDecoder colorDecoder = TiffColorDecoderFactory.Create(this.ColorType, this.BitsPerSample.Bits(), this.ColorMap); + TiffBaseColorDecoder colorDecoder = TiffColorDecoderFactory.Create(this.ColorType, this.BitsPerSample, this.ColorMap); for (int stripIndex = 0; stripIndex < stripOffsets.Length; stripIndex++) { diff --git a/src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs b/src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs index eeac6a33c2..a71c4cb054 100644 --- a/src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs +++ b/src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs @@ -69,7 +69,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff options.Predictor = frameMetadata.Predictor ?? TiffPredictor.None; options.PhotometricInterpretation = frameMetadata.PhotometricInterpretation ?? TiffPhotometricInterpretation.Rgb; options.BitsPerPixel = frameMetadata.BitsPerPixel != null ? (int)frameMetadata.BitsPerPixel.Value : (int)TiffBitsPerPixel.Bit24; - options.BitsPerSample = GetBitsPerSample(frameMetadata.BitsPerPixel); + options.BitsPerSample = frameMetadata.BitsPerSample ?? Array.Empty(); options.ParseColorType(exifProfile); options.ParseCompression(frameMetadata.Compression, exifProfile); @@ -99,26 +99,27 @@ namespace SixLabors.ImageSharp.Formats.Tiff { case TiffPhotometricInterpretation.WhiteIsZero: { - if (options.BitsPerSample.Bits().Length != 1) + if (options.BitsPerSample.Length != 1) { TiffThrowHelper.ThrowNotSupported("The number of samples in the TIFF BitsPerSample entry is not supported."); } - switch (options.BitsPerSample) + ushort bitsPerChannel = options.BitsPerSample[0]; + switch (bitsPerChannel) { - case TiffBitsPerSample.Bit8: + case 8: { options.ColorType = TiffColorType.WhiteIsZero8; break; } - case TiffBitsPerSample.Bit4: + case 4: { options.ColorType = TiffColorType.WhiteIsZero4; break; } - case TiffBitsPerSample.Bit1: + case 1: { options.ColorType = TiffColorType.WhiteIsZero1; break; @@ -136,26 +137,27 @@ namespace SixLabors.ImageSharp.Formats.Tiff case TiffPhotometricInterpretation.BlackIsZero: { - if (options.BitsPerSample.Bits().Length != 1) + if (options.BitsPerSample.Length != 1) { TiffThrowHelper.ThrowNotSupported("The number of samples in the TIFF BitsPerSample entry is not supported."); } - switch (options.BitsPerSample) + ushort bitsPerChannel = options.BitsPerSample[0]; + switch (bitsPerChannel) { - case TiffBitsPerSample.Bit8: + case 8: { options.ColorType = TiffColorType.BlackIsZero8; break; } - case TiffBitsPerSample.Bit4: + case 4: { options.ColorType = TiffColorType.BlackIsZero4; break; } - case TiffBitsPerSample.Bit1: + case 1: { options.ColorType = TiffColorType.BlackIsZero1; break; @@ -173,30 +175,31 @@ namespace SixLabors.ImageSharp.Formats.Tiff case TiffPhotometricInterpretation.Rgb: { - if (options.BitsPerSample.Bits().Length != 3) + if (options.BitsPerSample.Length != 3) { TiffThrowHelper.ThrowNotSupported("The number of samples in the TIFF BitsPerSample entry is not supported."); } if (options.PlanarConfiguration == TiffPlanarConfiguration.Chunky) { - switch (options.BitsPerSample) + ushort bitsPerChannel = options.BitsPerSample[0]; + switch (bitsPerChannel) { - case TiffBitsPerSample.Bit42: + case 14: options.ColorType = TiffColorType.Rgb141414; break; - case TiffBitsPerSample.Bit30: + case 10: options.ColorType = TiffColorType.Rgb101010; break; - case TiffBitsPerSample.Bit24: + case 8: options.ColorType = TiffColorType.Rgb888; break; - case TiffBitsPerSample.Bit12: + case 4: options.ColorType = TiffColorType.Rgb444; break; - case TiffBitsPerSample.Bit6: + case 2: options.ColorType = TiffColorType.Rgb222; break; default: @@ -217,7 +220,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff options.ColorMap = exifProfile.GetValue(ExifTag.ColorMap)?.Value; if (options.ColorMap != null) { - if (options.BitsPerSample.Bits().Length != 1) + if (options.BitsPerSample.Length != 1) { TiffThrowHelper.ThrowNotSupported("The number of samples in the TIFF BitsPerSample entry is not supported."); } @@ -291,18 +294,5 @@ namespace SixLabors.ImageSharp.Formats.Tiff } } } - - private static TiffBitsPerSample GetBitsPerSample(TiffBitsPerPixel? bitsPerPixel) => bitsPerPixel switch - { - TiffBitsPerPixel.Bit1 => TiffBitsPerSample.Bit1, - TiffBitsPerPixel.Bit4 => TiffBitsPerSample.Bit4, - TiffBitsPerPixel.Bit6 => TiffBitsPerSample.Bit6, - TiffBitsPerPixel.Bit8 => TiffBitsPerSample.Bit8, - TiffBitsPerPixel.Bit12 => TiffBitsPerSample.Bit12, - TiffBitsPerPixel.Bit24 => TiffBitsPerSample.Bit24, - TiffBitsPerPixel.Bit30 => TiffBitsPerSample.Bit30, - TiffBitsPerPixel.Bit42 => TiffBitsPerSample.Bit42, - _ => throw new NotSupportedException("The bits per pixel are not supported"), - }; } } diff --git a/src/ImageSharp/Formats/Tiff/TiffFrameMetadata.cs b/src/ImageSharp/Formats/Tiff/TiffFrameMetadata.cs index 25a0578e91..ef7573d3e0 100644 --- a/src/ImageSharp/Formats/Tiff/TiffFrameMetadata.cs +++ b/src/ImageSharp/Formats/Tiff/TiffFrameMetadata.cs @@ -35,6 +35,11 @@ namespace SixLabors.ImageSharp.Formats.Tiff /// public TiffBitsPerPixel? BitsPerPixel { get; set; } + /// + /// Gets or sets number of bits per component. + /// + public ushort[] BitsPerSample { get; set; } + /// /// Gets or sets the compression scheme used on the image data. /// @@ -72,8 +77,8 @@ namespace SixLabors.ImageSharp.Formats.Tiff { if (profile != null) { - ushort[] bitsPerSample = profile.GetValue(ExifTag.BitsPerSample)?.Value; - meta.BitsPerPixel = BitsPerPixelFromBitsPerSample(bitsPerSample); + meta.BitsPerSample = profile.GetValue(ExifTag.BitsPerSample)?.Value; + meta.BitsPerPixel = BitsPerPixelFromBitsPerSample(meta.BitsPerSample); meta.Compression = (TiffCompression?)profile.GetValue(ExifTag.Compression)?.Value; meta.PhotometricInterpretation = (TiffPhotometricInterpretation?)profile.GetValue(ExifTag.PhotometricInterpretation)?.Value; diff --git a/tests/ImageSharp.Tests/Formats/Tiff/TiffMetadataTests.cs b/tests/ImageSharp.Tests/Formats/Tiff/TiffMetadataTests.cs index ab350f720e..c80d9fc165 100644 --- a/tests/ImageSharp.Tests/Formats/Tiff/TiffMetadataTests.cs +++ b/tests/ImageSharp.Tests/Formats/Tiff/TiffMetadataTests.cs @@ -66,7 +66,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff { Assert.NotNull(frameMetaData); Assert.NotNull(frameMetaData.BitsPerPixel); - Assert.Equal(TiffBitsPerSample.Bit4, (TiffBitsPerSample)frameMetaData.BitsPerPixel); + Assert.Equal(TiffBitsPerPixel.Bit4, frameMetaData.BitsPerPixel); Assert.Equal(TiffCompression.Lzw, frameMetaData.Compression); Assert.Equal(TiffPhotometricInterpretation.PaletteColor, frameMetaData.PhotometricInterpretation); Assert.Equal(TiffPredictor.None, frameMetaData.Predictor);