diff --git a/src/ImageSharp/Formats/Tiff/Constants/TiffConstants.cs b/src/ImageSharp/Formats/Tiff/Constants/TiffConstants.cs
index f56488a52f..2327528b0e 100644
--- a/src/ImageSharp/Formats/Tiff/Constants/TiffConstants.cs
+++ b/src/ImageSharp/Formats/Tiff/Constants/TiffConstants.cs
@@ -110,6 +110,11 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Constants
///
public static readonly ushort[] BitsPerSampleRgb8Bit = { 8, 8, 8 };
+ ///
+ /// The bits per sample for color images with 10 bits for each color channel.
+ ///
+ public static readonly ushort[] BitsPerSampleRgb10Bit = { 10, 10, 10 };
+
///
/// 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 2c59fdf137..9ebf48620a 100644
--- a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorDecoderFactory{TPixel}.cs
+++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorDecoderFactory{TPixel}.cs
@@ -87,6 +87,16 @@ namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation
DebugGuard.IsTrue(colorMap == null, "colorMap");
return new Rgb888TiffColor();
+ case TiffColorType.Rgb101010:
+ DebugGuard.IsTrue(
+ bitsPerSample.Length == 3
+ && bitsPerSample[0] == 10
+ && bitsPerSample[1] == 10
+ && bitsPerSample[2] == 10,
+ "bitsPerSample");
+ DebugGuard.IsTrue(colorMap == null, "colorMap");
+ return new RgbTiffColor(bitsPerSample);
+
case TiffColorType.PaletteColor:
DebugGuard.NotNull(bitsPerSample, "bitsPerSample");
DebugGuard.NotNull(colorMap, "colorMap");
diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorType.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorType.cs
index 1d6535fd71..afa86b1430 100644
--- a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorType.cs
+++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorType.cs
@@ -73,6 +73,11 @@ namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation
///
Rgb888,
+ ///
+ /// RGB color image with 10 bits for each channel.
+ ///
+ Rgb101010,
+
///
/// RGB Full Color. Planar configuration of data.
///
diff --git a/src/ImageSharp/Formats/Tiff/TiffBitsPerPixel.cs b/src/ImageSharp/Formats/Tiff/TiffBitsPerPixel.cs
index 0dee1105bb..dc1ef0fd6e 100644
--- a/src/ImageSharp/Formats/Tiff/TiffBitsPerPixel.cs
+++ b/src/ImageSharp/Formats/Tiff/TiffBitsPerPixel.cs
@@ -41,5 +41,12 @@ namespace SixLabors.ImageSharp.Formats.Tiff
/// 24 bits per pixel. One byte for each color channel.
///
Bit24 = 24,
+
+ ///
+ /// 30 bits per pixel. 10 bit for each color channel.
+ ///
+ /// Note: The TiffEncoder does not yet support 10 bits per color channel and will default to 24 bits per pixel instead.
+ ///
+ Bit30 = 30,
}
}
diff --git a/src/ImageSharp/Formats/Tiff/TiffBitsPerSample.cs b/src/ImageSharp/Formats/Tiff/TiffBitsPerSample.cs
index 0a4962b530..02378ded30 100644
--- a/src/ImageSharp/Formats/Tiff/TiffBitsPerSample.cs
+++ b/src/ImageSharp/Formats/Tiff/TiffBitsPerSample.cs
@@ -42,5 +42,10 @@ namespace SixLabors.ImageSharp.Formats.Tiff
/// 24 bits per sample, each color channel has 8 Bits.
///
Bit24 = 24,
+
+ ///
+ /// Thirty bits per sample, each channel has 10 bits.
+ ///
+ Bit30 = 30,
}
}
diff --git a/src/ImageSharp/Formats/Tiff/TiffBitsPerSampleExtensions.cs b/src/ImageSharp/Formats/Tiff/TiffBitsPerSampleExtensions.cs
index 923e355f40..51a5a53a7a 100644
--- a/src/ImageSharp/Formats/Tiff/TiffBitsPerSampleExtensions.cs
+++ b/src/ImageSharp/Formats/Tiff/TiffBitsPerSampleExtensions.cs
@@ -29,6 +29,8 @@ namespace SixLabors.ImageSharp.Formats.Tiff
return TiffConstants.BitsPerSampleRgb4Bit;
case TiffBitsPerSample.Bit24:
return TiffConstants.BitsPerSampleRgb8Bit;
+ case TiffBitsPerSample.Bit30:
+ return TiffConstants.BitsPerSampleRgb10Bit;
default:
return Array.Empty();
@@ -45,6 +47,13 @@ namespace SixLabors.ImageSharp.Formats.Tiff
switch (bitsPerSample.Length)
{
case 3:
+ 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])
diff --git a/src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs b/src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs
index 1c2ee2443d..cf6ac6dc75 100644
--- a/src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs
+++ b/src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs
@@ -182,6 +182,10 @@ namespace SixLabors.ImageSharp.Formats.Tiff
{
switch (options.BitsPerSample)
{
+ case TiffBitsPerSample.Bit30:
+ options.ColorType = TiffColorType.Rgb101010;
+ break;
+
case TiffBitsPerSample.Bit24:
options.ColorType = TiffColorType.Rgb888;
break;
@@ -292,6 +296,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff
TiffBitsPerPixel.Bit8 => TiffBitsPerSample.Bit8,
TiffBitsPerPixel.Bit12 => TiffBitsPerSample.Bit12,
TiffBitsPerPixel.Bit24 => TiffBitsPerSample.Bit24,
+ TiffBitsPerPixel.Bit30 => TiffBitsPerSample.Bit30,
_ => throw new NotSupportedException("The bits per pixel are not supported"),
};
}
diff --git a/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs b/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs
index b61a0c0e1a..edfa215cc5 100644
--- a/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs
+++ b/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs
@@ -321,7 +321,8 @@ namespace SixLabors.ImageSharp.Formats.Tiff
break;
case TiffBitsPerPixel.Bit6:
case TiffBitsPerPixel.Bit12:
- // Encoding 12 and 6 bits per pixel is not yet supported. Default to 24 bits.
+ case TiffBitsPerPixel.Bit30:
+ // Encoding 30, 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 ad27ed0fcc..0dd8e0e22e 100644
--- a/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs
@@ -111,6 +111,12 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
public void TiffDecoder_CanDecode_12Bit(TestImageProvider provider)
where TPixel : unmanaged, IPixel => TestTiffDecoder(provider);
+ [Theory]
+ [WithFile(FlowerRgb101010Contiguous, PixelTypes.Rgba32)]
+ [WithFile(FlowerRgb101010Planar, PixelTypes.Rgba32)]
+ public void TiffDecoder_CanDecode_30Bit(TestImageProvider provider)
+ where TPixel : unmanaged, IPixel => TestTiffDecoder(provider);
+
[Theory]
[WithFile(GrayscaleDeflateMultistrip, PixelTypes.Rgba32)]
[WithFile(RgbDeflateMultistrip, PixelTypes.Rgba32)]
diff --git a/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderTests.cs
index 1b3104e728..19cfc42e4f 100644
--- a/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderTests.cs
@@ -78,6 +78,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
}
[Theory]
+ [InlineData(TiffBitsPerPixel.Bit30)]
[InlineData(TiffBitsPerPixel.Bit12)]
[InlineData(TiffBitsPerPixel.Bit6)]
public void EncoderOptions_UnsupportedBitPerPixel_DefaultTo24Bits(TiffBitsPerPixel bitsPerPixel)
diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs
index 3eff09c75f..05045d06a4 100644
--- a/tests/ImageSharp.Tests/TestImages.cs
+++ b/tests/ImageSharp.Tests/TestImages.cs
@@ -560,6 +560,8 @@ namespace SixLabors.ImageSharp.Tests
public const string RgbPaletteDeflate = "Tiff/rgb_palette_deflate.tiff";
public const string Flower4BitPalette = "Tiff/flower-palette-04.tiff";
public const string Flower4BitPaletteGray = "Tiff/flower-minisblack-04.tiff";
+ public const string FlowerRgb101010Contiguous = "Tiff/flower-rgb-contig-10.tiff";
+ public const string FlowerRgb101010Planar = "Tiff/flower-rgb-planar-10.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";
diff --git a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs
index 885d12e774..30c2214b5a 100644
--- a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs
+++ b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs
@@ -87,7 +87,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs
MemoryGroup framePixels = frame.PixelBuffer.FastMemoryGroup;
using IUnsafePixelCollection pixels = magicFrame.GetPixelsUnsafe();
- if (magicFrame.Depth == 8 || magicFrame.Depth == 4 || magicFrame.Depth == 2 || magicFrame.Depth == 1)
+ if (magicFrame.Depth == 8 || magicFrame.Depth == 4 || magicFrame.Depth == 2 || magicFrame.Depth == 1 || magicFrame.Depth == 10)
{
byte[] data = pixels.ToByteArray(PixelMapping.RGBA);
diff --git a/tests/Images/Input/Tiff/flower-rgb-contig-10.tiff b/tests/Images/Input/Tiff/flower-rgb-contig-10.tiff
new file mode 100644
index 0000000000..2b271c8004
--- /dev/null
+++ b/tests/Images/Input/Tiff/flower-rgb-contig-10.tiff
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:68168ea1c2e50e674a7c5c41e5b055c881adf8cb940d0fd033a927a7ebdd7b6f
+size 12117
diff --git a/tests/Images/Input/Tiff/flower-rgb-planar-10.tiff b/tests/Images/Input/Tiff/flower-rgb-planar-10.tiff
new file mode 100644
index 0000000000..be0acd6465
--- /dev/null
+++ b/tests/Images/Input/Tiff/flower-rgb-planar-10.tiff
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:7f53948d4a36c80f45d70a315d2e76514ec41cabe982c06dbbd0d47e671120e2
+size 12211