Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, in
{
for (int x = 0; x < pixelRow.Length; x++)
{
ushort intensity = TiffUtils.ConvertToShortBigEndian(data.Slice(offset, 2));
ushort intensity = TiffUtils.ConvertToUShortBigEndian(data.Slice(offset, 2));
offset += 2;

pixelRow[x] = TiffUtils.ColorFromL16(l16, intensity, color);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// 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 'BlackIsZero' photometric interpretation for 24-bit grayscale images.
/// </summary>
internal class BlackIsZero24TiffColor<TPixel> : TiffBaseColorDecoder<TPixel>
where TPixel : unmanaged, IPixel<TPixel>
{
private readonly bool isBigEndian;

/// <summary>
/// Initializes a new instance of the <see cref="BlackIsZero24TiffColor{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 BlackIsZero24TiffColor(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);
byte[] buffer = new byte[4];
int bufferStartIdx = this.isBigEndian ? 1 : 0;

Span<byte> bufferSpan = buffer.AsSpan(bufferStartIdx);
int offset = 0;
for (int y = top; y < top + height; y++)
{
Span<TPixel> pixelRow = pixels.GetRowSpan(y).Slice(left, width);
if (this.isBigEndian)
{
for (int x = 0; x < pixelRow.Length; x++)
{
data.Slice(offset, 3).CopyTo(bufferSpan);
ulong intensity = TiffUtils.ConvertToUIntBigEndian(buffer);
offset += 3;

pixelRow[x] = TiffUtils.ColorScaleTo24Bit(intensity, color);
}
}
else
{
for (int x = 0; x < pixelRow.Length; x++)
{
data.Slice(offset, 3).CopyTo(bufferSpan);
ulong intensity = TiffUtils.ConvertToUIntLittleEndian(buffer);
offset += 3;

pixelRow[x] = TiffUtils.ColorScaleTo24Bit(intensity, color);
}
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// 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 'BlackIsZero' photometric interpretation for 32-bit grayscale images.
/// </summary>
internal class BlackIsZero32TiffColor<TPixel> : TiffBaseColorDecoder<TPixel>
where TPixel : unmanaged, IPixel<TPixel>
{
private readonly bool isBigEndian;

/// <summary>
/// Initializes a new instance of the <see cref="BlackIsZero32TiffColor{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 BlackIsZero32TiffColor(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.GetRowSpan(y).Slice(left, width);
if (this.isBigEndian)
{
for (int x = 0; x < pixelRow.Length; x++)
{
ulong intensity = TiffUtils.ConvertToUIntBigEndian(data.Slice(offset, 4));
offset += 4;

pixelRow[x] = TiffUtils.ColorScaleTo32Bit(intensity, color);
}
}
else
{
for (int x = 0; x < pixelRow.Length; x++)
{
ulong intensity = TiffUtils.ConvertToUIntLittleEndian(data.Slice(offset, 4));
offset += 4;

pixelRow[x] = TiffUtils.ColorScaleTo32Bit(intensity, color);
}
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,11 @@ public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, in
{
for (int x = 0; x < pixelRow.Length; x++)
{
ulong r = TiffUtils.ConvertToShortBigEndian(data.Slice(offset, 2));
ulong r = TiffUtils.ConvertToUShortBigEndian(data.Slice(offset, 2));
offset += 2;
ulong g = TiffUtils.ConvertToShortBigEndian(data.Slice(offset, 2));
ulong g = TiffUtils.ConvertToUShortBigEndian(data.Slice(offset, 2));
offset += 2;
ulong b = TiffUtils.ConvertToShortBigEndian(data.Slice(offset, 2));
ulong b = TiffUtils.ConvertToUShortBigEndian(data.Slice(offset, 2));
offset += 2;

pixelRow[x] = TiffUtils.ColorFromRgba64(rgba, r, g, b, color);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
namespace SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation
{
/// <summary>
/// Implements the 'RGB' photometric interpretation with 'Planar' layout for all 16 bit.
/// Implements the 'RGB' photometric interpretation with 'Planar' layout for each color channel with 16 bit.
/// </summary>
internal class Rgb16PlanarTiffColor<TPixel> : TiffBasePlanarColorDecoder<TPixel>
where TPixel : unmanaged, IPixel<TPixel>
Expand Down Expand Up @@ -44,9 +44,9 @@ public override void Decode(IMemoryOwner<byte>[] data, Buffer2D<TPixel> pixels,
{
for (int x = 0; x < pixelRow.Length; x++)
{
ulong r = TiffUtils.ConvertToShortBigEndian(redData.Slice(offset, 2));
ulong g = TiffUtils.ConvertToShortBigEndian(greenData.Slice(offset, 2));
ulong b = TiffUtils.ConvertToShortBigEndian(blueData.Slice(offset, 2));
ulong r = TiffUtils.ConvertToUShortBigEndian(redData.Slice(offset, 2));
ulong g = TiffUtils.ConvertToUShortBigEndian(greenData.Slice(offset, 2));
ulong b = TiffUtils.ConvertToUShortBigEndian(blueData.Slice(offset, 2));

offset += 2;

Expand All @@ -57,9 +57,9 @@ public override void Decode(IMemoryOwner<byte>[] data, Buffer2D<TPixel> pixels,
{
for (int x = 0; x < pixelRow.Length; x++)
{
ulong r = TiffUtils.ConvertToShortLittleEndian(redData.Slice(offset, 2));
ulong g = TiffUtils.ConvertToShortLittleEndian(greenData.Slice(offset, 2));
ulong b = TiffUtils.ConvertToShortLittleEndian(blueData.Slice(offset, 2));
ulong r = TiffUtils.ConvertToUShortLittleEndian(redData.Slice(offset, 2));
ulong g = TiffUtils.ConvertToUShortLittleEndian(greenData.Slice(offset, 2));
ulong b = TiffUtils.ConvertToUShortLittleEndian(blueData.Slice(offset, 2));

offset += 2;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// 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 24 bits for each channel.
/// </summary>
internal class Rgb242424TiffColor<TPixel> : TiffBaseColorDecoder<TPixel>
where TPixel : unmanaged, IPixel<TPixel>
{
private readonly bool isBigEndian;

/// <summary>
/// Initializes a new instance of the <see cref="Rgb242424TiffColor{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 Rgb242424TiffColor(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];
int bufferStartIdx = this.isBigEndian ? 1 : 0;

Span<byte> bufferSpan = buffer.AsSpan(bufferStartIdx);
for (int y = top; y < top + height; y++)
{
Span<TPixel> pixelRow = pixels.GetRowSpan(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;

pixelRow[x] = TiffUtils.ColorScaleTo24Bit(r, g, b, 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;

pixelRow[x] = TiffUtils.ColorScaleTo24Bit(r, g, b, color);
}
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// 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 'Planar' layout for each color channel with 24 bit.
/// </summary>
internal class Rgb24PlanarTiffColor<TPixel> : TiffBasePlanarColorDecoder<TPixel>
where TPixel : unmanaged, IPixel<TPixel>
{
private readonly bool isBigEndian;

/// <summary>
/// Initializes a new instance of the <see cref="Rgb24PlanarTiffColor{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 Rgb24PlanarTiffColor(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);
byte[] buffer = new 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> bufferSpan = buffer.AsSpan(bufferStartIdx);

int offset = 0;
for (int y = top; y < top + height; y++)
{
Span<TPixel> pixelRow = pixels.GetRowSpan(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);

offset += 3;

pixelRow[x] = TiffUtils.ColorScaleTo24Bit(r, g, b, 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);

offset += 3;

pixelRow[x] = TiffUtils.ColorScaleTo24Bit(r, g, b, color);
}
}
}
}
}
}
Loading