Skip to content

Commit

Permalink
Merge pull request #2062 from SixLabors/bp/extrasamples2
Browse files Browse the repository at this point in the history
Add support for decoding Tiff images with associated alpha data
  • Loading branch information
JimBobSquarePants committed Mar 15, 2022
2 parents 7bd0e03 + 3ad23e8 commit aac0783
Show file tree
Hide file tree
Showing 53 changed files with 481 additions and 126 deletions.
10 changes: 5 additions & 5 deletions src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -323,12 +323,12 @@ private void ReadRle<TPixel>(BmpCompression compression, Buffer2D<TPixel> pixels
color.FromBgr24(Unsafe.As<byte, Bgr24>(ref colors[colorIdx * 4]));
break;
case RleSkippedPixelHandling.Transparent:
color.FromVector4(Vector4.Zero);
color.FromScaledVector4(Vector4.Zero);
break;

// Default handling for skipped pixels is black (which is what System.Drawing is also doing).
default:
color.FromVector4(new Vector4(0.0f, 0.0f, 0.0f, 1.0f));
color.FromScaledVector4(new Vector4(0.0f, 0.0f, 0.0f, 1.0f));
break;
}
}
Expand Down Expand Up @@ -395,12 +395,12 @@ private void ReadRle24<TPixel>(Buffer2D<TPixel> pixels, int width, int height, b
color.FromBgr24(Unsafe.As<byte, Bgr24>(ref bufferSpan[idx]));
break;
case RleSkippedPixelHandling.Transparent:
color.FromVector4(Vector4.Zero);
color.FromScaledVector4(Vector4.Zero);
break;

// Default handling for skipped pixels is black (which is what System.Drawing is also doing).
default:
color.FromVector4(new Vector4(0.0f, 0.0f, 0.0f, 1.0f));
color.FromScaledVector4(new Vector4(0.0f, 0.0f, 0.0f, 1.0f));
break;
}
}
Expand Down Expand Up @@ -1127,7 +1127,7 @@ private void ReadRgb32BitFields<TPixel>(Buffer2D<TPixel> pixels, int width, int
g * invMaxValueGreen,
b * invMaxValueBlue,
alpha);
color.FromVector4(vector4);
color.FromScaledVector4(vector4);
}
else
{
Expand Down
42 changes: 29 additions & 13 deletions src/ImageSharp/Formats/Tiff/Constants/TiffCompression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,6 @@ public enum TiffCompression : ushort
/// </summary>
Ccitt1D = 2,

/// <summary>
/// PackBits compression
/// </summary>
PackBits = 32773,

/// <summary>
/// T4-encoding: CCITT T.4 bi-level encoding (see Section 11 of the TIFF 6.0 specification).
/// </summary>
Expand Down Expand Up @@ -65,27 +60,48 @@ public enum TiffCompression : ushort
Deflate = 8,

/// <summary>
/// Deflate compression - old.
/// ITU-T Rec. T.82 coding, applying ITU-T Rec. T.85 (JBIG) (see RFC2301).
///
/// Note: The TIFF encoder does not support this compression and will default to use no compression instead,
/// Note: The TIFF encoder does not yet support this compression and will default to use no compression instead,
/// if this is chosen.
/// </summary>
OldDeflate = 32946,
ItuTRecT82 = 9,

/// <summary>
/// ITU-T Rec. T.82 coding, applying ITU-T Rec. T.85 (JBIG) (see RFC2301).
/// ITU-T Rec. T.43 representation, using ITU-T Rec. T.82 (JBIG) (see RFC2301).
///
/// Note: The TIFF encoder does not yet support this compression and will default to use no compression instead,
/// if this is chosen.
/// </summary>
ItuTRecT82 = 9,
ItuTRecT43 = 10,

/// <summary>
/// ITU-T Rec. T.43 representation, using ITU-T Rec. T.82 (JBIG) (see RFC2301).
/// NeXT 2-bit Grey Scale compression algorithm.
///
/// Note: The TIFF encoder does not yet support this compression and will default to use no compression instead,
/// Note: The TIFF encoder does not support this compression and will default to use no compression instead,
/// if this is chosen.
/// </summary>
NeXT = 32766,

/// <summary>
/// PackBits compression.
/// </summary>
PackBits = 32773,

/// <summary>
/// ThunderScan 4-bit compression.
///
/// Note: The TIFF encoder does not support this compression and will default to use no compression instead,
/// if this is chosen.
/// </summary>
ItuTRecT43 = 10
ThunderScan = 32809,

/// <summary>
/// Deflate compression - old.
///
/// Note: The TIFF encoder does not support this compression and will default to use no compression instead,
/// if this is chosen.
/// </summary>
OldDeflate = 32946,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, in
// we define our own defaults as a workaround. See: https://github.com/dotnet/runtime/issues/55623
L16 l16 = TiffUtils.L16Default;
var color = default(TPixel);
color.FromVector4(TiffUtils.Vector4Default);
color.FromScaledVector4(TiffUtils.Vector4Default);

int offset = 0;
for (int y = top; y < top + height; y++)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, in
// Note: due to an issue with netcore 2.1 and default values and unpredictable behavior with those,
// we define our own defaults as a workaround. See: https://github.com/dotnet/runtime/issues/55623
var color = default(TPixel);
color.FromVector4(TiffUtils.Vector4Default);
color.FromScaledVector4(TiffUtils.Vector4Default);
byte[] buffer = new byte[4];
int bufferStartIdx = this.isBigEndian ? 1 : 0;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, in
// Note: due to an issue with netcore 2.1 and default values and unpredictable behavior with those,
// we define our own defaults as a workaround. See: https://github.com/dotnet/runtime/issues/55623
var color = default(TPixel);
color.FromVector4(TiffUtils.Vector4Default);
color.FromScaledVector4(TiffUtils.Vector4Default);
byte[] buffer = new byte[4];

int offset = 0;
Expand All @@ -46,7 +46,7 @@ public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, in
offset += 4;

var colorVector = new Vector4(intensity, intensity, intensity, 1.0f);
color.FromVector4(colorVector);
color.FromScaledVector4(colorVector);
pixelRow[x] = color;
}
}
Expand All @@ -59,7 +59,7 @@ public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, in
offset += 4;

var colorVector = new Vector4(intensity, intensity, intensity, 1.0f);
color.FromVector4(colorVector);
color.FromScaledVector4(colorVector);
pixelRow[x] = color;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, in
// Note: due to an issue with netcore 2.1 and default values and unpredictable behavior with those,
// we define our own defaults as a workaround. See: https://github.com/dotnet/runtime/issues/55623
var color = default(TPixel);
color.FromVector4(TiffUtils.Vector4Default);
color.FromScaledVector4(TiffUtils.Vector4Default);

int offset = 0;
for (int y = top; y < top + height; y++)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, in
int value = bitReader.ReadBits(this.bitsPerSample0);
float intensity = value / this.factor;

color.FromVector4(new Vector4(intensity, intensity, intensity, 1.0f));
color.FromScaledVector4(new Vector4(intensity, intensity, intensity, 1.0f));
pixelRow[x] = color;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ private static TPixel[] GeneratePalette(ushort[] colorMap, int colorCount)
float r = colorMap[rOffset + i] / 65535F;
float g = colorMap[gOffset + i] / 65535F;
float b = colorMap[bOffset + i] / 65535F;
palette[i].FromVector4(new Vector4(r, g, b, 1.0f));
palette[i].FromScaledVector4(new Vector4(r, g, b, 1.0f));
}

return palette;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, in
// we define our own defaults as a workaround. See: https://github.com/dotnet/runtime/issues/55623
Rgba64 rgba = TiffUtils.Rgba64Default;
var color = default(TPixel);
color.FromVector4(TiffUtils.Vector4Default);
color.FromScaledVector4(TiffUtils.Vector4Default);

int offset = 0;

Expand All @@ -55,7 +55,7 @@ public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, in
ulong b = TiffUtils.ConvertToUShortBigEndian(data.Slice(offset, 2));
offset += 2;

pixelRow[x] = TiffUtils.ColorFromRgba64(rgba, r, g, b, color);
pixelRow[x] = TiffUtils.ColorFromRgb64(rgba, r, g, b, color);
}
}
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public override void Decode(IMemoryOwner<byte>[] data, Buffer2D<TPixel> pixels,
// we define our own defaults as a workaround. See: https://github.com/dotnet/runtime/issues/55623
Rgba64 rgba = TiffUtils.Rgba64Default;
var color = default(TPixel);
color.FromVector4(TiffUtils.Vector4Default);
color.FromScaledVector4(TiffUtils.Vector4Default);

Span<byte> redData = data[0].GetSpan();
Span<byte> greenData = data[1].GetSpan();
Expand All @@ -50,7 +50,7 @@ public override void Decode(IMemoryOwner<byte>[] data, Buffer2D<TPixel> pixels,

offset += 2;

pixelRow[x] = TiffUtils.ColorFromRgba64(rgba, r, g, b, color);
pixelRow[x] = TiffUtils.ColorFromRgb64(rgba, r, g, b, color);
}
}
else
Expand All @@ -63,7 +63,7 @@ public override void Decode(IMemoryOwner<byte>[] data, Buffer2D<TPixel> pixels,

offset += 2;

pixelRow[x] = TiffUtils.ColorFromRgba64(rgba, r, g, b, color);
pixelRow[x] = TiffUtils.ColorFromRgb64(rgba, r, g, b, color);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, in
// Note: due to an issue with netcore 2.1 and default values and unpredictable behavior with those,
// we define our own defaults as a workaround. See: https://github.com/dotnet/runtime/issues/55623
var color = default(TPixel);
color.FromVector4(TiffUtils.Vector4Default);
color.FromScaledVector4(TiffUtils.Vector4Default);
int offset = 0;
Span<byte> buffer = stackalloc byte[4];
int bufferStartIdx = this.isBigEndian ? 1 : 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public override void Decode(IMemoryOwner<byte>[] data, Buffer2D<TPixel> pixels,
// Note: due to an issue with netcore 2.1 and default values and unpredictable behavior with those,
// we define our own defaults as a workaround. See: https://github.com/dotnet/runtime/issues/55623
var color = default(TPixel);
color.FromVector4(TiffUtils.Vector4Default);
color.FromScaledVector4(TiffUtils.Vector4Default);
Span<byte> buffer = stackalloc byte[4];
int bufferStartIdx = this.isBigEndian ? 1 : 0;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, in
// Note: due to an issue with netcore 2.1 and default values and unpredictable behavior with those,
// we define our own defaults as a workaround. See: https://github.com/dotnet/runtime/issues/55623
var color = default(TPixel);
color.FromVector4(TiffUtils.Vector4Default);
color.FromScaledVector4(TiffUtils.Vector4Default);
int offset = 0;

for (int y = top; y < top + height; y++)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public override void Decode(IMemoryOwner<byte>[] data, Buffer2D<TPixel> pixels,
// Note: due to an issue with netcore 2.1 and default values and unpredictable behavior with those,
// we define our own defaults as a workaround. See: https://github.com/dotnet/runtime/issues/55623
var color = default(TPixel);
color.FromVector4(TiffUtils.Vector4Default);
color.FromScaledVector4(TiffUtils.Vector4Default);

Span<byte> redData = data[0].GetSpan();
Span<byte> greenData = data[1].GetSpan();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, in
// Note: due to an issue with netcore 2.1 and default values and unpredictable behavior with those,
// we define our own defaults as a workaround. See: https://github.com/dotnet/runtime/issues/55623
var color = default(TPixel);
color.FromVector4(TiffUtils.Vector4Default);
color.FromScaledVector4(TiffUtils.Vector4Default);
int offset = 0;
byte[] buffer = new byte[4];

Expand Down Expand Up @@ -57,7 +57,7 @@ public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, in
offset += 4;

var colorVector = new Vector4(r, g, b, 1.0f);
color.FromVector4(colorVector);
color.FromScaledVector4(colorVector);
pixelRow[x] = color;
}
}
Expand All @@ -78,7 +78,7 @@ public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, in
offset += 4;

var colorVector = new Vector4(r, g, b, 1.0f);
color.FromVector4(colorVector);
color.FromScaledVector4(colorVector);
pixelRow[x] = color;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public override void Decode(IMemoryOwner<byte>[] data, Buffer2D<TPixel> pixels,
float g = gBitReader.ReadBits(this.bitsPerSampleG) / this.gFactor;
float b = bBitReader.ReadBits(this.bitsPerSampleB) / this.bFactor;

color.FromVector4(new Vector4(r, g, b, 1.0f));
color.FromScaledVector4(new Vector4(r, g, b, 1.0f));
pixelRow[x] = color;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, in
float g = bitReader.ReadBits(this.bitsPerSampleG) / this.gFactor;
float b = bitReader.ReadBits(this.bitsPerSampleB) / this.bFactor;

color.FromVector4(new Vector4(r, g, b, 1.0f));
color.FromScaledVector4(new Vector4(r, g, b, 1.0f));
pixelRow[x] = color;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// Licensed under the Apache License, Version 2.0.

using System;
using System.Buffers;
using System.Numerics;
using SixLabors.ImageSharp.Formats.Tiff.Utils;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
Expand All @@ -18,15 +20,23 @@ internal class Rgba16161616TiffColor<TPixel> : TiffBaseColorDecoder<TPixel>

private readonly Configuration configuration;

private readonly MemoryAllocator memoryAllocator;

private readonly TiffExtraSampleType? extraSamplesType;

/// <summary>
/// Initializes a new instance of the <see cref="Rgba16161616TiffColor{TPixel}" /> class.
/// </summary>
/// <param name="configuration">The configuration.</param>
/// <param name="memoryAllocator">The memory allocator.</param>
/// <param name="isBigEndian">if set to <c>true</c> decodes the pixel data as big endian, otherwise as little endian.</param>
public Rgba16161616TiffColor(Configuration configuration, bool isBigEndian)
/// <param name="extraSamplesType">The type of the extra samples.</param>
public Rgba16161616TiffColor(Configuration configuration, MemoryAllocator memoryAllocator, TiffExtraSampleType? extraSamplesType, bool isBigEndian)
{
this.configuration = configuration;
this.isBigEndian = isBigEndian;
this.memoryAllocator = memoryAllocator;
this.extraSamplesType = extraSamplesType;
}

/// <inheritdoc/>
Expand All @@ -36,10 +46,13 @@ public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, in
// we define our own defaults as a workaround. See: https://github.com/dotnet/runtime/issues/55623
Rgba64 rgba = TiffUtils.Rgba64Default;
var color = default(TPixel);
color.FromVector4(TiffUtils.Vector4Default);
color.FromScaledVector4(TiffUtils.Vector4Default);

bool hasAssociatedAlpha = this.extraSamplesType.HasValue && this.extraSamplesType == TiffExtraSampleType.AssociatedAlphaData;
int offset = 0;

using IMemoryOwner<Vector4> vectors = hasAssociatedAlpha ? this.memoryAllocator.Allocate<Vector4>(width) : null;
Span<Vector4> vectorsSpan = hasAssociatedAlpha ? vectors.GetSpan() : Span<Vector4>.Empty;
for (int y = top; y < top + height; y++)
{
Span<TPixel> pixelRow = pixels.DangerousGetRowSpan(y).Slice(left, width);
Expand All @@ -57,7 +70,9 @@ public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, in
ulong a = TiffUtils.ConvertToUShortBigEndian(data.Slice(offset, 2));
offset += 2;

pixelRow[x] = TiffUtils.ColorFromRgba64(rgba, r, g, b, a, color);
pixelRow[x] = hasAssociatedAlpha ?
TiffUtils.ColorFromRgba64Premultiplied(rgba, r, g, b, a, color) :
TiffUtils.ColorFromRgba64(rgba, r, g, b, a, color);
}
}
else
Expand All @@ -69,6 +84,12 @@ public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, in
pixelRow,
pixelRow.Length);

if (hasAssociatedAlpha)
{
PixelOperations<TPixel>.Instance.ToVector4(this.configuration, pixelRow, vectorsSpan);
PixelOperations<TPixel>.Instance.FromVector4Destructive(this.configuration, vectorsSpan, pixelRow, PixelConversionModifiers.Premultiply | PixelConversionModifiers.Scale);
}

offset += byteCount;
}
}
Expand Down
Loading

0 comments on commit aac0783

Please sign in to comment.