Browse Source

Add test cases for tiled tiff, deflate compressed with predictor and color type Rgba16161616

pull/2878/head
Brian Popow 1 year ago
parent
commit
f804ca2e17
  1. 173
      src/ImageSharp/Formats/Tiff/Compression/HorizontalPredictor.cs
  2. 2
      tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs
  3. 2
      tests/ImageSharp.Tests/TestImages.cs
  4. 3
      tests/Images/Input/Tiff/tiled_rgba_64bit_big_endian_deflate_compressed_predictor.tiff
  5. 3
      tests/Images/Input/Tiff/tiled_rgba_64bit_little_endian_deflate_compressed_predictor.tiff

173
src/ImageSharp/Formats/Tiff/Compression/HorizontalPredictor.cs

@ -114,6 +114,17 @@ internal static class HorizontalPredictor
UndoRgb48BitLittleEndianRow(pixelBytes, width, y);
}
break;
case TiffColorType.Rgba16161616:
if (isBigEndian)
{
UndoRgb64BitBigEndianRow(pixelBytes, width, y);
}
else
{
UndoRgb64BitLittleEndianRow(pixelBytes, width, y);
}
break;
}
}
@ -504,6 +515,92 @@ internal static class HorizontalPredictor
}
}
private static void UndoRgb64BitBigEndianRow(Span<byte> pixelBytes, int width, int y)
{
int rowBytesCount = width * 8;
int offset = 0;
Span<byte> rowBytes = pixelBytes.Slice(y * rowBytesCount, rowBytesCount);
ushort r = TiffUtilities.ConvertToUShortBigEndian(rowBytes.Slice(offset, 2));
offset += 2;
ushort g = TiffUtilities.ConvertToUShortBigEndian(rowBytes.Slice(offset, 2));
offset += 2;
ushort b = TiffUtilities.ConvertToUShortBigEndian(rowBytes.Slice(offset, 2));
offset += 2;
ushort a = TiffUtilities.ConvertToUShortBigEndian(rowBytes.Slice(offset, 2));
offset += 2;
for (int x = 1; x < width; x++)
{
Span<byte> rowSpan = rowBytes.Slice(offset, 2);
ushort deltaR = TiffUtilities.ConvertToUShortBigEndian(rowSpan);
r += deltaR;
BinaryPrimitives.WriteUInt16BigEndian(rowSpan, r);
offset += 2;
rowSpan = rowBytes.Slice(offset, 2);
ushort deltaG = TiffUtilities.ConvertToUShortBigEndian(rowSpan);
g += deltaG;
BinaryPrimitives.WriteUInt16BigEndian(rowSpan, g);
offset += 2;
rowSpan = rowBytes.Slice(offset, 2);
ushort deltaB = TiffUtilities.ConvertToUShortBigEndian(rowSpan);
b += deltaB;
BinaryPrimitives.WriteUInt16BigEndian(rowSpan, b);
offset += 2;
rowSpan = rowBytes.Slice(offset, 2);
ushort deltaA = TiffUtilities.ConvertToUShortBigEndian(rowSpan);
a += deltaA;
BinaryPrimitives.WriteUInt16BigEndian(rowSpan, a);
offset += 2;
}
}
private static void UndoRgb64BitLittleEndianRow(Span<byte> pixelBytes, int width, int y)
{
int rowBytesCount = width * 8;
int offset = 0;
Span<byte> rowBytes = pixelBytes.Slice(y * rowBytesCount, rowBytesCount);
ushort r = TiffUtilities.ConvertToUShortLittleEndian(rowBytes.Slice(offset, 2));
offset += 2;
ushort g = TiffUtilities.ConvertToUShortLittleEndian(rowBytes.Slice(offset, 2));
offset += 2;
ushort b = TiffUtilities.ConvertToUShortLittleEndian(rowBytes.Slice(offset, 2));
offset += 2;
ushort a = TiffUtilities.ConvertToUShortLittleEndian(rowBytes.Slice(offset, 2));
offset += 2;
for (int x = 1; x < width; x++)
{
Span<byte> rowSpan = rowBytes.Slice(offset, 2);
ushort deltaR = TiffUtilities.ConvertToUShortLittleEndian(rowSpan);
r += deltaR;
BinaryPrimitives.WriteUInt16LittleEndian(rowSpan, r);
offset += 2;
rowSpan = rowBytes.Slice(offset, 2);
ushort deltaG = TiffUtilities.ConvertToUShortLittleEndian(rowSpan);
g += deltaG;
BinaryPrimitives.WriteUInt16LittleEndian(rowSpan, g);
offset += 2;
rowSpan = rowBytes.Slice(offset, 2);
ushort deltaB = TiffUtilities.ConvertToUShortLittleEndian(rowSpan);
b += deltaB;
BinaryPrimitives.WriteUInt16LittleEndian(rowSpan, b);
offset += 2;
rowSpan = rowBytes.Slice(offset, 2);
ushort deltaA = TiffUtilities.ConvertToUShortLittleEndian(rowSpan);
a += deltaA;
BinaryPrimitives.WriteUInt16LittleEndian(rowSpan, a);
offset += 2;
}
}
private static void UndoRgba64Bit(Span<byte> pixelBytes, int width, bool isBigEndian)
{
int rowBytesCount = width * 8;
@ -512,86 +609,14 @@ internal static class HorizontalPredictor
{
for (int y = 0; y < height; y++)
{
int offset = 0;
Span<byte> rowBytes = pixelBytes.Slice(y * rowBytesCount, rowBytesCount);
ushort r = TiffUtilities.ConvertToUShortBigEndian(rowBytes.Slice(offset, 2));
offset += 2;
ushort g = TiffUtilities.ConvertToUShortBigEndian(rowBytes.Slice(offset, 2));
offset += 2;
ushort b = TiffUtilities.ConvertToUShortBigEndian(rowBytes.Slice(offset, 2));
offset += 2;
ushort a = TiffUtilities.ConvertToUShortBigEndian(rowBytes.Slice(offset, 2));
offset += 2;
for (int x = 1; x < width; x++)
{
Span<byte> rowSpan = rowBytes.Slice(offset, 2);
ushort deltaR = TiffUtilities.ConvertToUShortBigEndian(rowSpan);
r += deltaR;
BinaryPrimitives.WriteUInt16BigEndian(rowSpan, r);
offset += 2;
rowSpan = rowBytes.Slice(offset, 2);
ushort deltaG = TiffUtilities.ConvertToUShortBigEndian(rowSpan);
g += deltaG;
BinaryPrimitives.WriteUInt16BigEndian(rowSpan, g);
offset += 2;
rowSpan = rowBytes.Slice(offset, 2);
ushort deltaB = TiffUtilities.ConvertToUShortBigEndian(rowSpan);
b += deltaB;
BinaryPrimitives.WriteUInt16BigEndian(rowSpan, b);
offset += 2;
rowSpan = rowBytes.Slice(offset, 2);
ushort deltaA = TiffUtilities.ConvertToUShortBigEndian(rowSpan);
a += deltaA;
BinaryPrimitives.WriteUInt16BigEndian(rowSpan, a);
offset += 2;
}
UndoRgb64BitBigEndianRow(pixelBytes, width, y);
}
}
else
{
for (int y = 0; y < height; y++)
{
int offset = 0;
Span<byte> rowBytes = pixelBytes.Slice(y * rowBytesCount, rowBytesCount);
ushort r = TiffUtilities.ConvertToUShortLittleEndian(rowBytes.Slice(offset, 2));
offset += 2;
ushort g = TiffUtilities.ConvertToUShortLittleEndian(rowBytes.Slice(offset, 2));
offset += 2;
ushort b = TiffUtilities.ConvertToUShortLittleEndian(rowBytes.Slice(offset, 2));
offset += 2;
ushort a = TiffUtilities.ConvertToUShortLittleEndian(rowBytes.Slice(offset, 2));
offset += 2;
for (int x = 1; x < width; x++)
{
Span<byte> rowSpan = rowBytes.Slice(offset, 2);
ushort deltaR = TiffUtilities.ConvertToUShortLittleEndian(rowSpan);
r += deltaR;
BinaryPrimitives.WriteUInt16LittleEndian(rowSpan, r);
offset += 2;
rowSpan = rowBytes.Slice(offset, 2);
ushort deltaG = TiffUtilities.ConvertToUShortLittleEndian(rowSpan);
g += deltaG;
BinaryPrimitives.WriteUInt16LittleEndian(rowSpan, g);
offset += 2;
rowSpan = rowBytes.Slice(offset, 2);
ushort deltaB = TiffUtilities.ConvertToUShortLittleEndian(rowSpan);
b += deltaB;
BinaryPrimitives.WriteUInt16LittleEndian(rowSpan, b);
offset += 2;
rowSpan = rowBytes.Slice(offset, 2);
ushort deltaA = TiffUtilities.ConvertToUShortLittleEndian(rowSpan);
a += deltaA;
BinaryPrimitives.WriteUInt16LittleEndian(rowSpan, a);
offset += 2;
}
UndoRgb64BitLittleEndianRow(pixelBytes, width, y);
}
}
}

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

@ -96,6 +96,8 @@ public class TiffDecoderTests : TiffDecoderBaseTester
[WithFile(TiledGray32BitBigEndianDeflateCompressedWithPredictor, PixelTypes.Rgba32)]
[WithFile(TiledRgb48BitLittleEndianDeflateCompressedWithPredictor, PixelTypes.Rgba32)]
[WithFile(TiledRgb48BitBigEndianDeflateCompressedWithPredictor, PixelTypes.Rgba32)]
[WithFile(TiledRgba64BitLittleEndianDeflateCompressedWithPredictor, PixelTypes.Rgba32)]
[WithFile(TiledRgba64BitBigEndianDeflateCompressedWithPredictor, PixelTypes.Rgba32)]
public void TiffDecoder_CanDecode_Tiled<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> => TestTiffDecoder(provider);

2
tests/ImageSharp.Tests/TestImages.cs

@ -995,6 +995,8 @@ public static class TestImages
public const string TiledGray32BitBigEndianDeflateCompressedWithPredictor = "Tiff/tiled_gray_32bit_big_endian_deflate_compressed_predictor.tiff";
public const string TiledRgb48BitLittleEndianDeflateCompressedWithPredictor = "Tiff/tiled_rgb_48bit_little_endian_deflate_compressed_predictor.tiff";
public const string TiledRgb48BitBigEndianDeflateCompressedWithPredictor = "Tiff/tiled_rgb_48bit_big_endian_deflate_compressed_predictor.tiff";
public const string TiledRgba64BitLittleEndianDeflateCompressedWithPredictor = "Tiff/tiled_rgba_64bit_little_endian_deflate_compressed_predictor.tiff";
public const string TiledRgba64BitBigEndianDeflateCompressedWithPredictor = "Tiff/tiled_rgba_64bit_big_endian_deflate_compressed_predictor.tiff";
// Images with alpha channel.
public const string Rgba2BitUnassociatedAlpha = "Tiff/RgbaUnassociatedAlpha2bit.tiff";

3
tests/Images/Input/Tiff/tiled_rgba_64bit_big_endian_deflate_compressed_predictor.tiff

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f456272c6948159ea17d6fa7d2a89e30521c1d4e29f0ad0b1a79894f122d2153
size 220119

3
tests/Images/Input/Tiff/tiled_rgba_64bit_little_endian_deflate_compressed_predictor.tiff

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