Browse Source

Add support for decoding 30 bit per pixel tiff's

pull/1647/head
Brian Popow 5 years ago
parent
commit
8e6fad805c
  1. 5
      src/ImageSharp/Formats/Tiff/Constants/TiffConstants.cs
  2. 10
      src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorDecoderFactory{TPixel}.cs
  3. 5
      src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorType.cs
  4. 7
      src/ImageSharp/Formats/Tiff/TiffBitsPerPixel.cs
  5. 5
      src/ImageSharp/Formats/Tiff/TiffBitsPerSample.cs
  6. 9
      src/ImageSharp/Formats/Tiff/TiffBitsPerSampleExtensions.cs
  7. 5
      src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs
  8. 3
      src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs
  9. 6
      tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs
  10. 1
      tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderTests.cs
  11. 2
      tests/ImageSharp.Tests/TestImages.cs
  12. 2
      tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs
  13. 3
      tests/Images/Input/Tiff/flower-rgb-contig-10.tiff
  14. 3
      tests/Images/Input/Tiff/flower-rgb-planar-10.tiff

5
src/ImageSharp/Formats/Tiff/Constants/TiffConstants.cs

@ -110,6 +110,11 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Constants
/// </summary>
public static readonly ushort[] BitsPerSampleRgb8Bit = { 8, 8, 8 };
/// <summary>
/// The bits per sample for color images with 10 bits for each color channel.
/// </summary>
public static readonly ushort[] BitsPerSampleRgb10Bit = { 10, 10, 10 };
/// <summary>
/// The list of mimetypes that equate to a tiff.
/// </summary>

10
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<TPixel>();
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<TPixel>(bitsPerSample);
case TiffColorType.PaletteColor:
DebugGuard.NotNull(bitsPerSample, "bitsPerSample");
DebugGuard.NotNull(colorMap, "colorMap");

5
src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorType.cs

@ -73,6 +73,11 @@ namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation
/// </summary>
Rgb888,
/// <summary>
/// RGB color image with 10 bits for each channel.
/// </summary>
Rgb101010,
/// <summary>
/// RGB Full Color. Planar configuration of data.
/// </summary>

7
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.
/// </summary>
Bit24 = 24,
/// <summary>
/// 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.
/// </summary>
Bit30 = 30,
}
}

5
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.
/// </summary>
Bit24 = 24,
/// <summary>
/// Thirty bits per sample, each channel has 10 bits.
/// </summary>
Bit30 = 30,
}
}

9
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<ushort>();
@ -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])

5
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"),
};
}

3
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:

6
tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs

@ -111,6 +111,12 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
public void TiffDecoder_CanDecode_12Bit<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> => TestTiffDecoder(provider);
[Theory]
[WithFile(FlowerRgb101010Contiguous, PixelTypes.Rgba32)]
[WithFile(FlowerRgb101010Planar, PixelTypes.Rgba32)]
public void TiffDecoder_CanDecode_30Bit<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> => TestTiffDecoder(provider);
[Theory]
[WithFile(GrayscaleDeflateMultistrip, PixelTypes.Rgba32)]
[WithFile(RgbDeflateMultistrip, PixelTypes.Rgba32)]

1
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)

2
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";

2
tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs

@ -87,7 +87,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs
MemoryGroup<TPixel> framePixels = frame.PixelBuffer.FastMemoryGroup;
using IUnsafePixelCollection<ushort> 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);

3
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

3
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
Loading…
Cancel
Save