mirror of https://github.com/SixLabors/ImageSharp
committed by
GitHub
51 changed files with 1463 additions and 45 deletions
@ -0,0 +1,77 @@ |
|||
// 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 'RGB' photometric interpretation with an alpha channel and with 16 bits for each channel.
|
|||
/// </summary>
|
|||
internal class Rgba16161616TiffColor<TPixel> : TiffBaseColorDecoder<TPixel> |
|||
where TPixel : unmanaged, IPixel<TPixel> |
|||
{ |
|||
private readonly bool isBigEndian; |
|||
|
|||
private readonly Configuration configuration; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Rgba16161616TiffColor{TPixel}" /> class.
|
|||
/// </summary>
|
|||
/// <param name="configuration">The configuration.</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) |
|||
{ |
|||
this.configuration = configuration; |
|||
this.isBigEndian = isBigEndian; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, int left, int top, int width, int height) |
|||
{ |
|||
// 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
|
|||
Rgba64 rgba = TiffUtils.Rgba64Default; |
|||
var color = default(TPixel); |
|||
color.FromVector4(TiffUtils.Vector4Default); |
|||
|
|||
int offset = 0; |
|||
|
|||
for (int y = top; y < top + height; y++) |
|||
{ |
|||
Span<TPixel> pixelRow = pixels.DangerousGetRowSpan(y).Slice(left, width); |
|||
|
|||
if (this.isBigEndian) |
|||
{ |
|||
for (int x = 0; x < pixelRow.Length; x++) |
|||
{ |
|||
ulong r = TiffUtils.ConvertToUShortBigEndian(data.Slice(offset, 2)); |
|||
offset += 2; |
|||
ulong g = TiffUtils.ConvertToUShortBigEndian(data.Slice(offset, 2)); |
|||
offset += 2; |
|||
ulong b = TiffUtils.ConvertToUShortBigEndian(data.Slice(offset, 2)); |
|||
offset += 2; |
|||
ulong a = TiffUtils.ConvertToUShortBigEndian(data.Slice(offset, 2)); |
|||
offset += 2; |
|||
|
|||
pixelRow[x] = TiffUtils.ColorFromRgba64(rgba, r, g, b, a, color); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
int byteCount = pixelRow.Length * 8; |
|||
PixelOperations<TPixel>.Instance.FromRgba64Bytes( |
|||
this.configuration, |
|||
data.Slice(offset, byteCount), |
|||
pixelRow, |
|||
pixelRow.Length); |
|||
|
|||
offset += byteCount; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,75 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using System.Buffers; |
|||
using SixLabors.ImageSharp.Formats.Tiff.Utils; |
|||
using SixLabors.ImageSharp.Memory; |
|||
using SixLabors.ImageSharp.PixelFormats; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation |
|||
{ |
|||
/// <summary>
|
|||
/// Implements the 'RGB' photometric interpretation with an alpha channel and with 'Planar' layout for each color channel with 16 bit.
|
|||
/// </summary>
|
|||
internal class Rgba16PlanarTiffColor<TPixel> : TiffBasePlanarColorDecoder<TPixel> |
|||
where TPixel : unmanaged, IPixel<TPixel> |
|||
{ |
|||
private readonly bool isBigEndian; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Rgba16PlanarTiffColor{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 Rgba16PlanarTiffColor(bool isBigEndian) => this.isBigEndian = isBigEndian; |
|||
|
|||
/// <inheritdoc/>
|
|||
public override void Decode(IMemoryOwner<byte>[] data, Buffer2D<TPixel> pixels, int left, int top, int width, int height) |
|||
{ |
|||
// 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
|
|||
Rgba64 rgba = TiffUtils.Rgba64Default; |
|||
var color = default(TPixel); |
|||
color.FromVector4(TiffUtils.Vector4Default); |
|||
|
|||
Span<byte> redData = data[0].GetSpan(); |
|||
Span<byte> greenData = data[1].GetSpan(); |
|||
Span<byte> blueData = data[2].GetSpan(); |
|||
Span<byte> alphaData = data[3].GetSpan(); |
|||
|
|||
int offset = 0; |
|||
for (int y = top; y < top + height; y++) |
|||
{ |
|||
Span<TPixel> pixelRow = pixels.DangerousGetRowSpan(y).Slice(left, width); |
|||
if (this.isBigEndian) |
|||
{ |
|||
for (int x = 0; x < pixelRow.Length; x++) |
|||
{ |
|||
ulong r = TiffUtils.ConvertToUShortBigEndian(redData.Slice(offset, 2)); |
|||
ulong g = TiffUtils.ConvertToUShortBigEndian(greenData.Slice(offset, 2)); |
|||
ulong b = TiffUtils.ConvertToUShortBigEndian(blueData.Slice(offset, 2)); |
|||
ulong a = TiffUtils.ConvertToUShortBigEndian(alphaData.Slice(offset, 2)); |
|||
|
|||
offset += 2; |
|||
|
|||
pixelRow[x] = TiffUtils.ColorFromRgba64(rgba, r, g, b, a, color); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
for (int x = 0; x < pixelRow.Length; x++) |
|||
{ |
|||
ulong r = TiffUtils.ConvertToUShortLittleEndian(redData.Slice(offset, 2)); |
|||
ulong g = TiffUtils.ConvertToUShortLittleEndian(greenData.Slice(offset, 2)); |
|||
ulong b = TiffUtils.ConvertToUShortLittleEndian(blueData.Slice(offset, 2)); |
|||
ulong a = TiffUtils.ConvertToUShortBigEndian(alphaData.Slice(offset, 2)); |
|||
|
|||
offset += 2; |
|||
|
|||
pixelRow[x] = TiffUtils.ColorFromRgba64(rgba, r, g, b, a, color); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,90 @@ |
|||
// 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 'RGB' photometric interpretation with an alpha channel and with 24 bits for each channel.
|
|||
/// </summary>
|
|||
internal class Rgba24242424TiffColor<TPixel> : TiffBaseColorDecoder<TPixel> |
|||
where TPixel : unmanaged, IPixel<TPixel> |
|||
{ |
|||
private readonly bool isBigEndian; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Rgba24242424TiffColor{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 Rgba24242424TiffColor(bool isBigEndian) => this.isBigEndian = isBigEndian; |
|||
|
|||
/// <inheritdoc/>
|
|||
public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, int left, int top, int width, int height) |
|||
{ |
|||
// 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); |
|||
int offset = 0; |
|||
Span<byte> buffer = stackalloc byte[4]; |
|||
int bufferStartIdx = this.isBigEndian ? 1 : 0; |
|||
|
|||
Span<byte> bufferSpan = buffer.Slice(bufferStartIdx); |
|||
for (int y = top; y < top + height; y++) |
|||
{ |
|||
Span<TPixel> pixelRow = pixels.DangerousGetRowSpan(y).Slice(left, width); |
|||
|
|||
if (this.isBigEndian) |
|||
{ |
|||
for (int x = 0; x < pixelRow.Length; x++) |
|||
{ |
|||
data.Slice(offset, 3).CopyTo(bufferSpan); |
|||
ulong r = TiffUtils.ConvertToUIntBigEndian(buffer); |
|||
offset += 3; |
|||
|
|||
data.Slice(offset, 3).CopyTo(bufferSpan); |
|||
ulong g = TiffUtils.ConvertToUIntBigEndian(buffer); |
|||
offset += 3; |
|||
|
|||
data.Slice(offset, 3).CopyTo(bufferSpan); |
|||
ulong b = TiffUtils.ConvertToUIntBigEndian(buffer); |
|||
offset += 3; |
|||
|
|||
data.Slice(offset, 3).CopyTo(bufferSpan); |
|||
ulong a = TiffUtils.ConvertToUIntBigEndian(buffer); |
|||
offset += 3; |
|||
|
|||
pixelRow[x] = TiffUtils.ColorScaleTo24Bit(r, g, b, a, color); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
for (int x = 0; x < pixelRow.Length; x++) |
|||
{ |
|||
data.Slice(offset, 3).CopyTo(bufferSpan); |
|||
ulong r = TiffUtils.ConvertToUIntLittleEndian(buffer); |
|||
offset += 3; |
|||
|
|||
data.Slice(offset, 3).CopyTo(bufferSpan); |
|||
ulong g = TiffUtils.ConvertToUIntLittleEndian(buffer); |
|||
offset += 3; |
|||
|
|||
data.Slice(offset, 3).CopyTo(bufferSpan); |
|||
ulong b = TiffUtils.ConvertToUIntLittleEndian(buffer); |
|||
offset += 3; |
|||
|
|||
data.Slice(offset, 3).CopyTo(bufferSpan); |
|||
ulong a = TiffUtils.ConvertToUIntLittleEndian(buffer); |
|||
offset += 3; |
|||
|
|||
pixelRow[x] = TiffUtils.ColorScaleTo24Bit(r, g, b, a, color); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,85 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using System.Buffers; |
|||
using SixLabors.ImageSharp.Formats.Tiff.Utils; |
|||
using SixLabors.ImageSharp.Memory; |
|||
using SixLabors.ImageSharp.PixelFormats; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation |
|||
{ |
|||
/// <summary>
|
|||
/// Implements the 'RGB' photometric interpretation with an alpha channel and with 'Planar' layout for each color channel with 24 bit.
|
|||
/// </summary>
|
|||
internal class Rgba24PlanarTiffColor<TPixel> : TiffBasePlanarColorDecoder<TPixel> |
|||
where TPixel : unmanaged, IPixel<TPixel> |
|||
{ |
|||
private readonly bool isBigEndian; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Rgba24PlanarTiffColor{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 Rgba24PlanarTiffColor(bool isBigEndian) => this.isBigEndian = isBigEndian; |
|||
|
|||
/// <inheritdoc/>
|
|||
public override void Decode(IMemoryOwner<byte>[] data, Buffer2D<TPixel> pixels, int left, int top, int width, int height) |
|||
{ |
|||
// 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); |
|||
Span<byte> buffer = stackalloc byte[4]; |
|||
int bufferStartIdx = this.isBigEndian ? 1 : 0; |
|||
|
|||
Span<byte> redData = data[0].GetSpan(); |
|||
Span<byte> greenData = data[1].GetSpan(); |
|||
Span<byte> blueData = data[2].GetSpan(); |
|||
Span<byte> alphaData = data[3].GetSpan(); |
|||
Span<byte> bufferSpan = buffer.Slice(bufferStartIdx); |
|||
|
|||
int offset = 0; |
|||
for (int y = top; y < top + height; y++) |
|||
{ |
|||
Span<TPixel> pixelRow = pixels.DangerousGetRowSpan(y).Slice(left, width); |
|||
if (this.isBigEndian) |
|||
{ |
|||
for (int x = 0; x < pixelRow.Length; x++) |
|||
{ |
|||
redData.Slice(offset, 3).CopyTo(bufferSpan); |
|||
ulong r = TiffUtils.ConvertToUIntBigEndian(buffer); |
|||
greenData.Slice(offset, 3).CopyTo(bufferSpan); |
|||
ulong g = TiffUtils.ConvertToUIntBigEndian(buffer); |
|||
blueData.Slice(offset, 3).CopyTo(bufferSpan); |
|||
ulong b = TiffUtils.ConvertToUIntBigEndian(buffer); |
|||
alphaData.Slice(offset, 3).CopyTo(bufferSpan); |
|||
ulong a = TiffUtils.ConvertToUIntBigEndian(buffer); |
|||
|
|||
offset += 3; |
|||
|
|||
pixelRow[x] = TiffUtils.ColorScaleTo24Bit(r, g, b, a, color); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
for (int x = 0; x < pixelRow.Length; x++) |
|||
{ |
|||
redData.Slice(offset, 3).CopyTo(bufferSpan); |
|||
ulong r = TiffUtils.ConvertToUIntLittleEndian(buffer); |
|||
greenData.Slice(offset, 3).CopyTo(bufferSpan); |
|||
ulong g = TiffUtils.ConvertToUIntLittleEndian(buffer); |
|||
blueData.Slice(offset, 3).CopyTo(bufferSpan); |
|||
ulong b = TiffUtils.ConvertToUIntLittleEndian(buffer); |
|||
alphaData.Slice(offset, 3).CopyTo(bufferSpan); |
|||
ulong a = TiffUtils.ConvertToUIntLittleEndian(buffer); |
|||
|
|||
offset += 3; |
|||
|
|||
pixelRow[x] = TiffUtils.ColorScaleTo24Bit(r, g, b, a, color); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,79 @@ |
|||
// 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 'RGB' photometric interpretation with an alpha channel and with 32 bits for each channel.
|
|||
/// </summary>
|
|||
internal class Rgba32323232TiffColor<TPixel> : TiffBaseColorDecoder<TPixel> |
|||
where TPixel : unmanaged, IPixel<TPixel> |
|||
{ |
|||
private readonly bool isBigEndian; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Rgba32323232TiffColor{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 Rgba32323232TiffColor(bool isBigEndian) => this.isBigEndian = isBigEndian; |
|||
|
|||
/// <inheritdoc/>
|
|||
public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, int left, int top, int width, int height) |
|||
{ |
|||
// 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); |
|||
int offset = 0; |
|||
|
|||
for (int y = top; y < top + height; y++) |
|||
{ |
|||
Span<TPixel> pixelRow = pixels.DangerousGetRowSpan(y).Slice(left, width); |
|||
|
|||
if (this.isBigEndian) |
|||
{ |
|||
for (int x = 0; x < pixelRow.Length; x++) |
|||
{ |
|||
ulong r = TiffUtils.ConvertToUIntBigEndian(data.Slice(offset, 4)); |
|||
offset += 4; |
|||
|
|||
ulong g = TiffUtils.ConvertToUIntBigEndian(data.Slice(offset, 4)); |
|||
offset += 4; |
|||
|
|||
ulong b = TiffUtils.ConvertToUIntBigEndian(data.Slice(offset, 4)); |
|||
offset += 4; |
|||
|
|||
ulong a = TiffUtils.ConvertToUIntBigEndian(data.Slice(offset, 4)); |
|||
offset += 4; |
|||
|
|||
pixelRow[x] = TiffUtils.ColorScaleTo32Bit(r, g, b, a, color); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
for (int x = 0; x < pixelRow.Length; x++) |
|||
{ |
|||
ulong r = TiffUtils.ConvertToUIntLittleEndian(data.Slice(offset, 4)); |
|||
offset += 4; |
|||
|
|||
ulong g = TiffUtils.ConvertToUIntLittleEndian(data.Slice(offset, 4)); |
|||
offset += 4; |
|||
|
|||
ulong b = TiffUtils.ConvertToUIntLittleEndian(data.Slice(offset, 4)); |
|||
offset += 4; |
|||
|
|||
ulong a = TiffUtils.ConvertToUIntLittleEndian(data.Slice(offset, 4)); |
|||
offset += 4; |
|||
|
|||
pixelRow[x] = TiffUtils.ColorScaleTo32Bit(r, g, b, a, color); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,74 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using System.Buffers; |
|||
using SixLabors.ImageSharp.Formats.Tiff.Utils; |
|||
using SixLabors.ImageSharp.Memory; |
|||
using SixLabors.ImageSharp.PixelFormats; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation |
|||
{ |
|||
/// <summary>
|
|||
/// Implements the 'RGB' photometric interpretation with an alpha channel and a 'Planar' layout for each color channel with 32 bit.
|
|||
/// </summary>
|
|||
internal class Rgba32PlanarTiffColor<TPixel> : TiffBasePlanarColorDecoder<TPixel> |
|||
where TPixel : unmanaged, IPixel<TPixel> |
|||
{ |
|||
private readonly bool isBigEndian; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Rgba32PlanarTiffColor{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 Rgba32PlanarTiffColor(bool isBigEndian) => this.isBigEndian = isBigEndian; |
|||
|
|||
/// <inheritdoc/>
|
|||
public override void Decode(IMemoryOwner<byte>[] data, Buffer2D<TPixel> pixels, int left, int top, int width, int height) |
|||
{ |
|||
// 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); |
|||
|
|||
Span<byte> redData = data[0].GetSpan(); |
|||
Span<byte> greenData = data[1].GetSpan(); |
|||
Span<byte> blueData = data[2].GetSpan(); |
|||
Span<byte> alphaData = data[3].GetSpan(); |
|||
|
|||
int offset = 0; |
|||
for (int y = top; y < top + height; y++) |
|||
{ |
|||
Span<TPixel> pixelRow = pixels.DangerousGetRowSpan(y).Slice(left, width); |
|||
if (this.isBigEndian) |
|||
{ |
|||
for (int x = 0; x < pixelRow.Length; x++) |
|||
{ |
|||
ulong r = TiffUtils.ConvertToUIntBigEndian(redData.Slice(offset, 4)); |
|||
ulong g = TiffUtils.ConvertToUIntBigEndian(greenData.Slice(offset, 4)); |
|||
ulong b = TiffUtils.ConvertToUIntBigEndian(blueData.Slice(offset, 4)); |
|||
ulong a = TiffUtils.ConvertToUIntBigEndian(alphaData.Slice(offset, 4)); |
|||
|
|||
offset += 4; |
|||
|
|||
pixelRow[x] = TiffUtils.ColorScaleTo32Bit(r, g, b, a, color); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
for (int x = 0; x < pixelRow.Length; x++) |
|||
{ |
|||
ulong r = TiffUtils.ConvertToUIntLittleEndian(redData.Slice(offset, 4)); |
|||
ulong g = TiffUtils.ConvertToUIntLittleEndian(greenData.Slice(offset, 4)); |
|||
ulong b = TiffUtils.ConvertToUIntLittleEndian(blueData.Slice(offset, 4)); |
|||
ulong a = TiffUtils.ConvertToUIntLittleEndian(alphaData.Slice(offset, 4)); |
|||
|
|||
offset += 4; |
|||
|
|||
pixelRow[x] = TiffUtils.ColorScaleTo32Bit(r, g, b, a, color); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,39 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using SixLabors.ImageSharp.Memory; |
|||
using SixLabors.ImageSharp.PixelFormats; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation |
|||
{ |
|||
/// <summary>
|
|||
/// Implements the 'RGB' photometric interpretation with an alpha channel and 8 bits per channel.
|
|||
/// </summary>
|
|||
internal class Rgba8888TiffColor<TPixel> : TiffBaseColorDecoder<TPixel> |
|||
where TPixel : unmanaged, IPixel<TPixel> |
|||
{ |
|||
private readonly Configuration configuration; |
|||
|
|||
public Rgba8888TiffColor(Configuration configuration) => this.configuration = configuration; |
|||
|
|||
/// <inheritdoc/>
|
|||
public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, int left, int top, int width, int height) |
|||
{ |
|||
int offset = 0; |
|||
|
|||
for (int y = top; y < top + height; y++) |
|||
{ |
|||
Span<TPixel> pixelRow = pixels.DangerousGetRowSpan(y).Slice(left, width); |
|||
int byteCount = pixelRow.Length * 4; |
|||
PixelOperations<TPixel>.Instance.FromRgba32Bytes( |
|||
this.configuration, |
|||
data.Slice(offset, byteCount), |
|||
pixelRow, |
|||
pixelRow.Length); |
|||
|
|||
offset += byteCount; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,97 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using System.Numerics; |
|||
using SixLabors.ImageSharp.Formats.Tiff.Utils; |
|||
using SixLabors.ImageSharp.Memory; |
|||
using SixLabors.ImageSharp.PixelFormats; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation |
|||
{ |
|||
/// <summary>
|
|||
/// Implements the 'RGB' photometric interpretation with an alpha channel and with 32 bits for each channel.
|
|||
/// </summary>
|
|||
internal class RgbaFloat32323232TiffColor<TPixel> : TiffBaseColorDecoder<TPixel> |
|||
where TPixel : unmanaged, IPixel<TPixel> |
|||
{ |
|||
private readonly bool isBigEndian; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="RgbaFloat32323232TiffColor{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 RgbaFloat32323232TiffColor(bool isBigEndian) => this.isBigEndian = isBigEndian; |
|||
|
|||
/// <inheritdoc/>
|
|||
public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, int left, int top, int width, int height) |
|||
{ |
|||
// 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); |
|||
int offset = 0; |
|||
byte[] buffer = new byte[4]; |
|||
|
|||
for (int y = top; y < top + height; y++) |
|||
{ |
|||
Span<TPixel> pixelRow = pixels.DangerousGetRowSpan(y).Slice(left, width); |
|||
|
|||
if (this.isBigEndian) |
|||
{ |
|||
for (int x = 0; x < pixelRow.Length; x++) |
|||
{ |
|||
data.Slice(offset, 4).CopyTo(buffer); |
|||
Array.Reverse(buffer); |
|||
float r = BitConverter.ToSingle(buffer, 0); |
|||
offset += 4; |
|||
|
|||
data.Slice(offset, 4).CopyTo(buffer); |
|||
Array.Reverse(buffer); |
|||
float g = BitConverter.ToSingle(buffer, 0); |
|||
offset += 4; |
|||
|
|||
data.Slice(offset, 4).CopyTo(buffer); |
|||
Array.Reverse(buffer); |
|||
float b = BitConverter.ToSingle(buffer, 0); |
|||
offset += 4; |
|||
|
|||
data.Slice(offset, 4).CopyTo(buffer); |
|||
Array.Reverse(buffer); |
|||
float a = BitConverter.ToSingle(buffer, 0); |
|||
offset += 4; |
|||
|
|||
var colorVector = new Vector4(r, g, b, a); |
|||
color.FromVector4(colorVector); |
|||
pixelRow[x] = color; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
for (int x = 0; x < pixelRow.Length; x++) |
|||
{ |
|||
data.Slice(offset, 4).CopyTo(buffer); |
|||
float r = BitConverter.ToSingle(buffer, 0); |
|||
offset += 4; |
|||
|
|||
data.Slice(offset, 4).CopyTo(buffer); |
|||
float g = BitConverter.ToSingle(buffer, 0); |
|||
offset += 4; |
|||
|
|||
data.Slice(offset, 4).CopyTo(buffer); |
|||
float b = BitConverter.ToSingle(buffer, 0); |
|||
offset += 4; |
|||
|
|||
data.Slice(offset, 4).CopyTo(buffer); |
|||
float a = BitConverter.ToSingle(buffer, 0); |
|||
offset += 4; |
|||
|
|||
var colorVector = new Vector4(r, g, b, a); |
|||
color.FromVector4(colorVector); |
|||
pixelRow[x] = color; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,87 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// 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; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation |
|||
{ |
|||
/// <summary>
|
|||
/// Implements the 'RGB' photometric interpretation with an alpha channel and with 'Planar' layout (for all bit depths).
|
|||
/// </summary>
|
|||
internal class RgbaPlanarTiffColor<TPixel> : TiffBasePlanarColorDecoder<TPixel> |
|||
where TPixel : unmanaged, IPixel<TPixel> |
|||
{ |
|||
private readonly float rFactor; |
|||
|
|||
private readonly float gFactor; |
|||
|
|||
private readonly float bFactor; |
|||
|
|||
private readonly float aFactor; |
|||
|
|||
private readonly ushort bitsPerSampleR; |
|||
|
|||
private readonly ushort bitsPerSampleG; |
|||
|
|||
private readonly ushort bitsPerSampleB; |
|||
|
|||
private readonly ushort bitsPerSampleA; |
|||
|
|||
public RgbaPlanarTiffColor(TiffBitsPerSample bitsPerSample) |
|||
{ |
|||
this.bitsPerSampleR = bitsPerSample.Channel0; |
|||
this.bitsPerSampleG = bitsPerSample.Channel1; |
|||
this.bitsPerSampleB = bitsPerSample.Channel2; |
|||
this.bitsPerSampleA = bitsPerSample.Channel3; |
|||
|
|||
this.rFactor = (1 << this.bitsPerSampleR) - 1.0f; |
|||
this.gFactor = (1 << this.bitsPerSampleG) - 1.0f; |
|||
this.bFactor = (1 << this.bitsPerSampleB) - 1.0f; |
|||
this.aFactor = (1 << this.bitsPerSampleA) - 1.0f; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Decodes pixel data using the current photometric interpretation.
|
|||
/// </summary>
|
|||
/// <param name="data">The buffers to read image data from.</param>
|
|||
/// <param name="pixels">The image buffer to write pixels to.</param>
|
|||
/// <param name="left">The x-coordinate of the left-hand side of the image block.</param>
|
|||
/// <param name="top">The y-coordinate of the top of the image block.</param>
|
|||
/// <param name="width">The width of the image block.</param>
|
|||
/// <param name="height">The height of the image block.</param>
|
|||
public override void Decode(IMemoryOwner<byte>[] data, Buffer2D<TPixel> pixels, int left, int top, int width, int height) |
|||
{ |
|||
var color = default(TPixel); |
|||
|
|||
var rBitReader = new BitReader(data[0].GetSpan()); |
|||
var gBitReader = new BitReader(data[1].GetSpan()); |
|||
var bBitReader = new BitReader(data[2].GetSpan()); |
|||
var aBitReader = new BitReader(data[3].GetSpan()); |
|||
|
|||
for (int y = top; y < top + height; y++) |
|||
{ |
|||
Span<TPixel> pixelRow = pixels.DangerousGetRowSpan(y).Slice(left, width); |
|||
for (int x = 0; x < pixelRow.Length; x++) |
|||
{ |
|||
float r = rBitReader.ReadBits(this.bitsPerSampleR) / this.rFactor; |
|||
float g = gBitReader.ReadBits(this.bitsPerSampleG) / this.gFactor; |
|||
float b = bBitReader.ReadBits(this.bitsPerSampleB) / this.bFactor; |
|||
float a = aBitReader.ReadBits(this.bitsPerSampleA) / this.aFactor; |
|||
|
|||
color.FromVector4(new Vector4(r, g, b, a)); |
|||
pixelRow[x] = color; |
|||
} |
|||
|
|||
rBitReader.NextRow(); |
|||
gBitReader.NextRow(); |
|||
bBitReader.NextRow(); |
|||
aBitReader.NextRow(); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,72 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using System.Numerics; |
|||
using SixLabors.ImageSharp.Formats.Tiff.Utils; |
|||
using SixLabors.ImageSharp.Memory; |
|||
using SixLabors.ImageSharp.PixelFormats; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation |
|||
{ |
|||
/// <summary>
|
|||
/// Implements the 'RGB' photometric interpretation with alpha channel (for all bit depths).
|
|||
/// </summary>
|
|||
internal class RgbaTiffColor<TPixel> : TiffBaseColorDecoder<TPixel> |
|||
where TPixel : unmanaged, IPixel<TPixel> |
|||
{ |
|||
private readonly float rFactor; |
|||
|
|||
private readonly float gFactor; |
|||
|
|||
private readonly float bFactor; |
|||
|
|||
private readonly float aFactor; |
|||
|
|||
private readonly ushort bitsPerSampleR; |
|||
|
|||
private readonly ushort bitsPerSampleG; |
|||
|
|||
private readonly ushort bitsPerSampleB; |
|||
|
|||
private readonly ushort bitsPerSampleA; |
|||
|
|||
public RgbaTiffColor(TiffBitsPerSample bitsPerSample) |
|||
{ |
|||
this.bitsPerSampleR = bitsPerSample.Channel0; |
|||
this.bitsPerSampleG = bitsPerSample.Channel1; |
|||
this.bitsPerSampleB = bitsPerSample.Channel2; |
|||
this.bitsPerSampleA = bitsPerSample.Channel3; |
|||
|
|||
this.rFactor = (1 << this.bitsPerSampleR) - 1.0f; |
|||
this.gFactor = (1 << this.bitsPerSampleG) - 1.0f; |
|||
this.bFactor = (1 << this.bitsPerSampleB) - 1.0f; |
|||
this.aFactor = (1 << this.bitsPerSampleA) - 1.0f; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, int left, int top, int width, int height) |
|||
{ |
|||
var color = default(TPixel); |
|||
|
|||
var bitReader = new BitReader(data); |
|||
|
|||
for (int y = top; y < top + height; y++) |
|||
{ |
|||
Span<TPixel> pixelRow = pixels.DangerousGetRowSpan(y).Slice(left, width); |
|||
for (int x = 0; x < pixelRow.Length; x++) |
|||
{ |
|||
float r = bitReader.ReadBits(this.bitsPerSampleR) / this.rFactor; |
|||
float g = bitReader.ReadBits(this.bitsPerSampleG) / this.gFactor; |
|||
float b = bitReader.ReadBits(this.bitsPerSampleB) / this.bFactor; |
|||
float a = bitReader.ReadBits(this.bitsPerSampleB) / this.aFactor; |
|||
|
|||
color.FromVector4(new Vector4(r, g, b, a)); |
|||
pixelRow[x] = color; |
|||
} |
|||
|
|||
bitReader.NextRow(); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Tiff |
|||
{ |
|||
/// <summary>
|
|||
/// Description of extra components.
|
|||
/// </summary>
|
|||
internal enum TiffExtraSampleType |
|||
{ |
|||
/// <summary>
|
|||
/// The data is unspecified, not supported.
|
|||
/// </summary>
|
|||
UnspecifiedData = 0, |
|||
|
|||
/// <summary>
|
|||
/// The extra data is associated alpha data (with pre-multiplied color).
|
|||
/// </summary>
|
|||
AssociatedAlphaData = 1, |
|||
|
|||
/// <summary>
|
|||
/// The extra data is unassociated alpha data is transparency information that logically exists independent of an image;
|
|||
/// it is commonly called a soft matte.
|
|||
/// </summary>
|
|||
UnassociatedAlphaData = 2 |
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:7f78ef11e4044d13ea3bf699e33472a708df3a5cc817dc41edb4df184f127f2b |
|||
size 294278 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:d9c2d6f4e16677d9fdfb38cc2bfb7df05eedbb8dc0e3c26a6dba9b427c2c698a |
|||
size 294278 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:53e9ff25da2a2a7a613328cfaf33799df51fe150586fb8de52070e8cc8830d97 |
|||
size 353078 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:caff76e01bc39b7a295f01a11e3787a6487ac002af5586dd956166a9c91eb048 |
|||
size 353078 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:9193b6a194be970b2cfb26369fa487fd6ec2f1656af11df2e48f1d6b0971bbf8 |
|||
size 411878 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:888bc84af8dffc4565b215412a8a2bb56f0c78211a082b893d87595cd9f555c1 |
|||
size 411878 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:6eae92c012ad56c084929e0a2aff7c93091224d9f8ab7f52f71b845792d6b763 |
|||
size 470678 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:cbab54f221956215266c35bfd26fdfb123e092e3836e2401b9f24e1c5b23516e |
|||
size 470678 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:fd9fa514619604275cede0b4747291db2f8e5ad02095565c891ace2b537d6336 |
|||
size 705878 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:915ca9bbda952fc9ac78b44be07dab603948d51fb1a274935905e73cfe5bb0b9 |
|||
size 705878 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:f650c49faed4fd19b5527a0771489110090948e4ed33daa53b42c1776e288d89 |
|||
size 59078 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:8cad4c5f42d77539ce1f67efa7e0ed1fa4f5dd32b3269e5862453d878c6b18d7 |
|||
size 941078 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:8874322776b8620573c26a3c84b8c7c9bf0aeaa7d68a7fef009f8838d14dca5b |
|||
size 941078 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:d0d89ddcda8525799b90c1cb4a15f3ea1cf399c2259017f219b1d09876161587 |
|||
size 88478 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:be006e56c2c2f34686293e8a5f4397a7bf873ff927d4dd0808cac90310569254 |
|||
size 117878 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:2928f06ef146625f5c696272901a63644699e3410dc155b7e4e470009a7f6dfc |
|||
size 147278 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:514ce84d3506aab7360b24f63aa1da1ea66abd9b1e534a12487d03486a7e593b |
|||
size 176678 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:234401d70156cc748a67992919f8780bb855bc5e87e404b573f61b5eb4817dcf |
|||
size 266816 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:6bc4325ce7be8a16d23c559300c79c3228c2f5a4c266844ba49763a32d29f10e |
|||
size 470710 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:08f8c284f7a9a6f362c09a418d85a94a1fe09bfc3f4cfe6859a82d6814718091 |
|||
size 470710 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:8ba4da7d63931f4462113e00bdee9e66e333ca42a47a33f62057c248bf4696ef |
|||
size 705910 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:862ec9153cc755aa3ece8965a9d001a630ff756dfb018a9474661730482964cb |
|||
size 705910 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:dc4f67dacd3262418769831aeabf99c9a88a9674fabf9a08c8b3d3e47ac6d07a |
|||
size 941110 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:a98a0176f5db7af5b22c74f4a518c2df1055b5ca7e732f63426b3df8090fc313 |
|||
size 941110 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:2185ef9a84701bcff104d4f2fe40171ed853e5d02a2049b209ee2a4c65105ea9 |
|||
size 235502 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:3b778a97467b1475c47c71b5f029c23b0962309095b8702cfc81c8fbaf4b8edb |
|||
size 3886 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:44a53ffce2bfd3f1010a1fe232c8010708458880230f11b75ea3ef16b5164ce1 |
|||
size 6208 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:3d1db5b448aa9d61dd38dfb86e91e04fd0779a9c68cc2073913bcee3c635b5fe |
|||
size 7412 |
|||
Loading…
Reference in new issue