diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/RgbTiffColor.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/RgbTiffColor.cs
new file mode 100644
index 0000000000..e62ee7dc93
--- /dev/null
+++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/RgbTiffColor.cs
@@ -0,0 +1,56 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageSharp.Formats.Tiff
+{
+ using System;
+ using System.Numerics;
+ using System.Runtime.CompilerServices;
+ using ImageSharp;
+ using ImageSharp.PixelFormats;
+
+ ///
+ /// Implements the 'RGB' photometric interpretation (for all bit depths).
+ ///
+ internal static class RgbTiffColor
+ {
+ ///
+ /// Decodes pixel data using the current photometric interpretation.
+ ///
+ /// The pixel format.
+ /// The buffer to read image data from.
+ /// The number of bits per sample for each pixel.
+ /// 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.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static void Decode(byte[] data, uint[] bitsPerSample, PixelAccessor pixels, int left, int top, int width, int height)
+ where TPixel : struct, IPixel
+ {
+ TPixel color = default(TPixel);
+
+ BitReader bitReader = new BitReader(data);
+ float rFactor = (float)Math.Pow(2, bitsPerSample[0]) - 1.0f;
+ float gFactor = (float)Math.Pow(2, bitsPerSample[1]) - 1.0f;
+ float bFactor = (float)Math.Pow(2, bitsPerSample[2]) - 1.0f;
+
+ for (int y = top; y < top + height; y++)
+ {
+ for (int x = left; x < left + width; x++)
+ {
+ float r = ((float)bitReader.ReadBits(bitsPerSample[0])) / rFactor;
+ float g = ((float)bitReader.ReadBits(bitsPerSample[1])) / gFactor;
+ float b = ((float)bitReader.ReadBits(bitsPerSample[2])) / bFactor;
+ color.PackFromVector4(new Vector4(r, g, b, 1.0f));
+ pixels[x, y] = color;
+ }
+
+ bitReader.NextRow();
+ }
+ }
+ }
+}
diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorType.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorType.cs
index c63d6febd1..5d85f6553a 100644
--- a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorType.cs
+++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorType.cs
@@ -53,6 +53,11 @@ namespace ImageSharp.Formats.Tiff
///
/// Palette-color.
///
- PaletteColor
+ PaletteColor,
+
+ ///
+ /// RGB Full Color.
+ ///
+ Rgb,
}
}
diff --git a/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs b/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs
index 5ebce1f046..e31706674c 100644
--- a/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs
+++ b/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs
@@ -389,6 +389,27 @@ namespace ImageSharp.Formats
break;
}
+ case TiffPhotometricInterpretation.Rgb:
+ {
+ if (this.BitsPerSample.Length == 3)
+ {
+ if (this.BitsPerSample[0] == 8 && this.BitsPerSample[1] == 8 && this.BitsPerSample[2] == 8)
+ {
+ this.ColorType = TiffColorType.Rgb;
+ }
+ else
+ {
+ this.ColorType = TiffColorType.Rgb;
+ }
+ }
+ else
+ {
+ throw new NotSupportedException("The number of samples in the TIFF BitsPerSample entry is not supported.");
+ }
+
+ break;
+ }
+
case TiffPhotometricInterpretation.PaletteColor:
{
if (ifd.TryGetIfdEntry(TiffTags.ColorMap, out TiffIfdEntry colorMapEntry))
@@ -505,6 +526,9 @@ namespace ImageSharp.Formats
case TiffColorType.BlackIsZero8:
BlackIsZero8TiffColor.Decode(data, pixels, left, top, width, height);
break;
+ case TiffColorType.Rgb:
+ RgbTiffColor.Decode(data, this.BitsPerSample, pixels, left, top, width, height);
+ break;
case TiffColorType.PaletteColor:
PaletteTiffColor.Decode(data, this.BitsPerSample, this.ColorMap, pixels, left, top, width, height);
break;
diff --git a/tests/ImageSharp.Formats.Tiff.Tests/Formats/Tiff/PhotometricInterpretation/RgbTiffColorTests.cs b/tests/ImageSharp.Formats.Tiff.Tests/Formats/Tiff/PhotometricInterpretation/RgbTiffColorTests.cs
new file mode 100644
index 0000000000..c67913d655
--- /dev/null
+++ b/tests/ImageSharp.Formats.Tiff.Tests/Formats/Tiff/PhotometricInterpretation/RgbTiffColorTests.cs
@@ -0,0 +1,151 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageSharp.Tests
+{
+ using System.Collections.Generic;
+ using Xunit;
+
+ using ImageSharp.Formats.Tiff;
+
+ public class RgbTiffColorTests : PhotometricInterpretationTestBase
+ {
+ private static Rgba32 Rgb4_000 = new Rgba32(0, 0, 0, 255);
+ private static Rgba32 Rgb4_444 = new Rgba32(68, 68, 68, 255);
+ private static Rgba32 Rgb4_888 = new Rgba32(136, 136, 136, 255);
+ private static Rgba32 Rgb4_CCC = new Rgba32(204, 204, 204, 255);
+ private static Rgba32 Rgb4_FFF = new Rgba32(255, 255, 255, 255);
+ private static Rgba32 Rgb4_F00 = new Rgba32(255, 0, 0, 255);
+ private static Rgba32 Rgb4_0F0 = new Rgba32(0, 255, 0, 255);
+ private static Rgba32 Rgb4_00F = new Rgba32(0, 0, 255, 255);
+ private static Rgba32 Rgb4_F0F = new Rgba32(255, 0, 255, 255);
+ private static Rgba32 Rgb4_400 = new Rgba32(68, 0, 0, 255);
+ private static Rgba32 Rgb4_800 = new Rgba32(136, 0, 0, 255);
+ private static Rgba32 Rgb4_C00 = new Rgba32(204, 0, 0, 255);
+ private static Rgba32 Rgb4_48C = new Rgba32(68, 136, 204, 255);
+
+ private static byte[] Rgb4_Bytes4x4 = new byte[] { 0x00, 0x0F, 0xFF, 0x00, 0x0F, 0xFF,
+ 0xF0, 0x00, 0xF0, 0x00, 0xFF, 0x0F,
+ 0x40, 0x08, 0x00, 0xC0, 0x04, 0x8C,
+ 0x00, 0x04, 0x44, 0x88, 0x8C, 0xCC };
+
+ private static Rgba32[][] Rgb4_Result4x4 = new[] { new[] { Rgb4_000, Rgb4_FFF, Rgb4_000, Rgb4_FFF },
+ new[] { Rgb4_F00, Rgb4_0F0, Rgb4_00F, Rgb4_F0F },
+ new[] { Rgb4_400, Rgb4_800, Rgb4_C00, Rgb4_48C },
+ new[] { Rgb4_000, Rgb4_444, Rgb4_888, Rgb4_CCC }};
+
+ private static byte[] Rgb4_Bytes3x4 = new byte[] { 0x00, 0x0F, 0xFF, 0x00, 0x00,
+ 0xF0, 0x00, 0xF0, 0x00, 0xF0,
+ 0x40, 0x08, 0x00, 0xC0, 0x00,
+ 0x00, 0x04, 0x44, 0x88, 0x80 };
+
+ private static Rgba32[][] Rgb4_Result3x4 = new[] { new[] { Rgb4_000, Rgb4_FFF, Rgb4_000 },
+ new[] { Rgb4_F00, Rgb4_0F0, Rgb4_00F },
+ new[] { Rgb4_400, Rgb4_800, Rgb4_C00 },
+ new[] { Rgb4_000, Rgb4_444, Rgb4_888 }};
+
+ public static IEnumerable