From f804ca2e177c8eea9dfbec05a0b7cb585d413667 Mon Sep 17 00:00:00 2001 From: Brian Popow Date: Sun, 9 Feb 2025 19:23:56 +0100 Subject: [PATCH] Add test cases for tiled tiff, deflate compressed with predictor and color type Rgba16161616 --- .../Tiff/Compression/HorizontalPredictor.cs | 173 ++++++++++-------- .../Formats/Tiff/TiffDecoderTests.cs | 2 + tests/ImageSharp.Tests/TestImages.cs | 2 + ...g_endian_deflate_compressed_predictor.tiff | 3 + ...e_endian_deflate_compressed_predictor.tiff | 3 + 5 files changed, 109 insertions(+), 74 deletions(-) create mode 100644 tests/Images/Input/Tiff/tiled_rgba_64bit_big_endian_deflate_compressed_predictor.tiff create mode 100644 tests/Images/Input/Tiff/tiled_rgba_64bit_little_endian_deflate_compressed_predictor.tiff diff --git a/src/ImageSharp/Formats/Tiff/Compression/HorizontalPredictor.cs b/src/ImageSharp/Formats/Tiff/Compression/HorizontalPredictor.cs index 16c7d9d0b..bc3113a6c 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/HorizontalPredictor.cs +++ b/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 pixelBytes, int width, int y) + { + int rowBytesCount = width * 8; + int offset = 0; + + Span 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 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 pixelBytes, int width, int y) + { + int rowBytesCount = width * 8; + int offset = 0; + + Span 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 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 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 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 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 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 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); } } } diff --git a/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs index 3ef0d2998..9f7784313 100644 --- a/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs +++ b/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(TestImageProvider provider) where TPixel : unmanaged, IPixel => TestTiffDecoder(provider); diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 1bd681928..1c89cd9e2 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/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"; diff --git a/tests/Images/Input/Tiff/tiled_rgba_64bit_big_endian_deflate_compressed_predictor.tiff b/tests/Images/Input/Tiff/tiled_rgba_64bit_big_endian_deflate_compressed_predictor.tiff new file mode 100644 index 000000000..0def24460 --- /dev/null +++ b/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 diff --git a/tests/Images/Input/Tiff/tiled_rgba_64bit_little_endian_deflate_compressed_predictor.tiff b/tests/Images/Input/Tiff/tiled_rgba_64bit_little_endian_deflate_compressed_predictor.tiff new file mode 100644 index 000000000..bcd96a88b --- /dev/null +++ b/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