Browse Source

Tiff decoder now respects byte order for 16 bit gray images with white is zero

pull/1720/head
Brian Popow 5 years ago
parent
commit
cc16677172
  1. 5
      src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorDecoderFactory{TPixel}.cs
  2. 5
      src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorType.cs
  3. 48
      src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero16TiffColor{TPixel}.cs
  4. 6
      src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs
  5. 1
      tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs
  6. 1
      tests/ImageSharp.Tests/TestImages.cs
  7. 3
      tests/Images/Input/Tiff/flower-miniswhite-16_lsb.tiff

5
src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorDecoderFactory{TPixel}.cs

@ -32,6 +32,11 @@ namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation
DebugGuard.IsTrue(colorMap == null, "colorMap"); DebugGuard.IsTrue(colorMap == null, "colorMap");
return new WhiteIsZero8TiffColor<TPixel>(); return new WhiteIsZero8TiffColor<TPixel>();
case TiffColorType.WhiteIsZero16:
DebugGuard.IsTrue(bitsPerSample.Channels == 1 && bitsPerSample.Channel0 == 16, "bitsPerSample");
DebugGuard.IsTrue(colorMap == null, "colorMap");
return new WhiteIsZero16TiffColor<TPixel>(byteOrder == ByteOrder.BigEndian);
case TiffColorType.BlackIsZero: case TiffColorType.BlackIsZero:
DebugGuard.IsTrue(bitsPerSample.Channels == 1, "bitsPerSample"); DebugGuard.IsTrue(bitsPerSample.Channels == 1, "bitsPerSample");
DebugGuard.IsTrue(colorMap == null, "colorMap"); DebugGuard.IsTrue(colorMap == null, "colorMap");

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

@ -53,6 +53,11 @@ namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation
/// </summary> /// </summary>
WhiteIsZero8, WhiteIsZero8,
/// <summary>
/// Grayscale: 0 is imaged as white. The maximum value is imaged as black. Optimized implementation for 16-bit images.
/// </summary>
WhiteIsZero16,
/// <summary> /// <summary>
/// Palette-color. /// Palette-color.
/// </summary> /// </summary>

48
src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero16TiffColor{TPixel}.cs

@ -0,0 +1,48 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System;
using SixLabors.ImageSharp.Formats.Tiff.Utils;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation
{
/// <summary>
/// Implements the 'WhiteIsZero' photometric interpretation for 16-bit grayscale images.
/// </summary>
internal class WhiteIsZero16TiffColor<TPixel> : TiffBaseColorDecoder<TPixel>
where TPixel : unmanaged, IPixel<TPixel>
{
private readonly bool isBigEndian;
/// <summary>
/// Initializes a new instance of the <see cref="WhiteIsZero16TiffColor{TPixel}" /> class.
/// </summary>
/// <param name="isBigEndian">if set to <c>true</c> decodes the pixel data as big endian, otherwise as little endian.</param>
public WhiteIsZero16TiffColor(bool isBigEndian) => this.isBigEndian = isBigEndian;
/// <inheritdoc/>
public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, int left, int top, int width, int height)
{
var color = default(TPixel);
int offset = 0;
var l16 = default(L16);
for (int y = top; y < top + height; y++)
{
for (int x = left; x < left + width; x++)
{
ushort intensity = (ushort)(ushort.MaxValue - TiffUtils.ConvertToShort(data.Slice(offset, 2), this.isBigEndian));
offset += 2;
l16.PackedValue = intensity;
color.FromL16(l16);
pixels[x, y] = color;
}
}
}
}
}

6
src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs

@ -111,6 +111,12 @@ namespace SixLabors.ImageSharp.Formats.Tiff
switch (bitsPerChannel) switch (bitsPerChannel)
{ {
case 16:
{
options.ColorType = TiffColorType.WhiteIsZero16;
break;
}
case 8: case 8:
{ {
options.ColorType = TiffColorType.WhiteIsZero8; options.ColorType = TiffColorType.WhiteIsZero8;

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

@ -142,6 +142,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
[Theory] [Theory]
[WithFile(Flower16BitGrayLittleEndian, PixelTypes.Rgba32)] [WithFile(Flower16BitGrayLittleEndian, PixelTypes.Rgba32)]
[WithFile(Flower16BitGray, PixelTypes.Rgba32)] [WithFile(Flower16BitGray, PixelTypes.Rgba32)]
[WithFile(Flower16BitGrayMinIsWhiteLittleEndian, PixelTypes.Rgba32)]
public void TiffDecoder_CanDecode_16Bit<TPixel>(TestImageProvider<TPixel> provider) public void TiffDecoder_CanDecode_16Bit<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> => TestTiffDecoder(provider); where TPixel : unmanaged, IPixel<TPixel> => TestTiffDecoder(provider);

1
tests/ImageSharp.Tests/TestImages.cs

@ -583,6 +583,7 @@ namespace SixLabors.ImageSharp.Tests
public const string Flower14BitGray = "Tiff/flower-minisblack-14.tiff"; public const string Flower14BitGray = "Tiff/flower-minisblack-14.tiff";
public const string Flower16BitGray = "Tiff/flower-minisblack-16.tiff"; public const string Flower16BitGray = "Tiff/flower-minisblack-16.tiff";
public const string Flower16BitGrayLittleEndian = "Tiff/flower-minisblack-16_lsb.tiff"; public const string Flower16BitGrayLittleEndian = "Tiff/flower-minisblack-16_lsb.tiff";
public const string Flower16BitGrayMinIsWhiteLittleEndian = "Tiff/flower-miniswhite-16_lsb.tiff";
public const string Issues1716Rgb161616BitLittleEndian = "Tiff/Issues/Issue1716.tiff"; public const string Issues1716Rgb161616BitLittleEndian = "Tiff/Issues/Issue1716.tiff";
public const string SmallRgbDeflate = "Tiff/rgb_small_deflate.tiff"; public const string SmallRgbDeflate = "Tiff/rgb_small_deflate.tiff";

3
tests/Images/Input/Tiff/flower-miniswhite-16_lsb.tiff

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:435c92b453587e1943940111b66afabf70307beb0e1d65e9701fd9bb753eead2
size 6588
Loading…
Cancel
Save