From 47c67558cbaef446a8f685aaa4e1384964094964 Mon Sep 17 00:00:00 2001 From: Brian Popow Date: Sun, 9 Feb 2025 13:14:58 +0100 Subject: [PATCH] Add test cases for tiled 32 bit gray tiff's --- .../Tiff/Compression/HorizontalPredictor.cs | 80 +++++++++++++------ .../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, 64 insertions(+), 26 deletions(-) create mode 100644 tests/Images/Input/Tiff/tiled_gray_32bit_big_endian_deflate_compressed_predictor.tiff create mode 100644 tests/Images/Input/Tiff/tiled_gray_32bit_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 e37a83528..ce1736ca7 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/HorizontalPredictor.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/HorizontalPredictor.cs @@ -83,6 +83,18 @@ internal static class HorizontalPredictor UndoGray16BitLittleEndianRow(pixelBytes, width, y); } + break; + case TiffColorType.BlackIsZero32: + case TiffColorType.WhiteIsZero32: + if (isBigEndian) + { + UndoGray32BitBigEndianRow(pixelBytes, width, y); + } + else + { + UndoGray32BitLittleEndianRow(pixelBytes, width, y); + } + break; case TiffColorType.Rgb888: case TiffColorType.CieLab: @@ -266,6 +278,46 @@ internal static class HorizontalPredictor } } + private static void UndoGray32BitBigEndianRow(Span pixelBytes, int width, int y) + { + int rowBytesCount = width * 4; + int height = pixelBytes.Length / rowBytesCount; + + int offset = 0; + Span rowBytes = pixelBytes.Slice(y * rowBytesCount, rowBytesCount); + uint pixelValue = TiffUtilities.ConvertToUIntBigEndian(rowBytes.Slice(offset, 4)); + offset += 4; + + for (int x = 1; x < width; x++) + { + Span rowSpan = rowBytes.Slice(offset, 4); + uint diff = TiffUtilities.ConvertToUIntBigEndian(rowSpan); + pixelValue += diff; + BinaryPrimitives.WriteUInt32BigEndian(rowSpan, pixelValue); + offset += 4; + } + } + + private static void UndoGray32BitLittleEndianRow(Span pixelBytes, int width, int y) + { + int rowBytesCount = width * 4; + int height = pixelBytes.Length / rowBytesCount; + + int offset = 0; + Span rowBytes = pixelBytes.Slice(y * rowBytesCount, rowBytesCount); + uint pixelValue = TiffUtilities.ConvertToUIntLittleEndian(rowBytes.Slice(offset, 4)); + offset += 4; + + for (int x = 1; x < width; x++) + { + Span rowSpan = rowBytes.Slice(offset, 4); + uint diff = TiffUtilities.ConvertToUIntLittleEndian(rowSpan); + pixelValue += diff; + BinaryPrimitives.WriteUInt32LittleEndian(rowSpan, pixelValue); + offset += 4; + } + } + private static void UndoGray32Bit(Span pixelBytes, int width, bool isBigEndian) { int rowBytesCount = width * 4; @@ -274,38 +326,14 @@ internal static class HorizontalPredictor { for (int y = 0; y < height; y++) { - int offset = 0; - Span rowBytes = pixelBytes.Slice(y * rowBytesCount, rowBytesCount); - uint pixelValue = TiffUtilities.ConvertToUIntBigEndian(rowBytes.Slice(offset, 4)); - offset += 4; - - for (int x = 1; x < width; x++) - { - Span rowSpan = rowBytes.Slice(offset, 4); - uint diff = TiffUtilities.ConvertToUIntBigEndian(rowSpan); - pixelValue += diff; - BinaryPrimitives.WriteUInt32BigEndian(rowSpan, pixelValue); - offset += 4; - } + UndoGray32BitBigEndianRow(pixelBytes, width, y); } } else { for (int y = 0; y < height; y++) { - int offset = 0; - Span rowBytes = pixelBytes.Slice(y * rowBytesCount, rowBytesCount); - uint pixelValue = TiffUtilities.ConvertToUIntLittleEndian(rowBytes.Slice(offset, 4)); - offset += 4; - - for (int x = 1; x < width; x++) - { - Span rowSpan = rowBytes.Slice(offset, 4); - uint diff = TiffUtilities.ConvertToUIntLittleEndian(rowSpan); - pixelValue += diff; - BinaryPrimitives.WriteUInt32LittleEndian(rowSpan, pixelValue); - offset += 4; - } + UndoGray32BitLittleEndianRow(pixelBytes, width, y); } } } diff --git a/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs index 00f498e9a..c0d48e694 100644 --- a/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs @@ -92,6 +92,8 @@ public class TiffDecoderTests : TiffDecoderBaseTester [WithFile(TiledGrayDeflateCompressedWithPredictor, PixelTypes.Rgba32)] [WithFile(TiledGray16BitLittleEndianDeflateCompressedWithPredictor, PixelTypes.Rgba32)] [WithFile(TiledGray16BitBigEndianDeflateCompressedWithPredictor, PixelTypes.Rgba32)] + [WithFile(TiledGray32BitLittleEndianDeflateCompressedWithPredictor, PixelTypes.Rgba32)] + [WithFile(TiledGray32BitBigEndianDeflateCompressedWithPredictor, 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 fee925af3..d0007184c 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -991,6 +991,8 @@ public static class TestImages public const string TiledGrayDeflateCompressedWithPredictor = "Tiff/tiled_gray_deflate_compressed_predictor.tiff"; public const string TiledGray16BitLittleEndianDeflateCompressedWithPredictor = "Tiff/tiled_gray_16bit_little_endian_deflate_compressed_predictor.tiff"; public const string TiledGray16BitBigEndianDeflateCompressedWithPredictor = "Tiff/tiled_gray_16bit_big_endian_deflate_compressed_predictor.tiff"; + public const string TiledGray32BitLittleEndianDeflateCompressedWithPredictor = "Tiff/tiled_gray_32bit_little_endian_deflate_compressed_predictor.tiff"; + public const string TiledGray32BitBigEndianDeflateCompressedWithPredictor = "Tiff/tiled_gray_32bit_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_gray_32bit_big_endian_deflate_compressed_predictor.tiff b/tests/Images/Input/Tiff/tiled_gray_32bit_big_endian_deflate_compressed_predictor.tiff new file mode 100644 index 000000000..17866b164 --- /dev/null +++ b/tests/Images/Input/Tiff/tiled_gray_32bit_big_endian_deflate_compressed_predictor.tiff @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b674439ce46a39377279755ffa372c5bd863ac7787165e95590c0a9c6c5d681e +size 82469 diff --git a/tests/Images/Input/Tiff/tiled_gray_32bit_little_endian_deflate_compressed_predictor.tiff b/tests/Images/Input/Tiff/tiled_gray_32bit_little_endian_deflate_compressed_predictor.tiff new file mode 100644 index 000000000..b524237c9 --- /dev/null +++ b/tests/Images/Input/Tiff/tiled_gray_32bit_little_endian_deflate_compressed_predictor.tiff @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3acfecebb3db8b549b7a20a3fdd967ba5a4cbb95cbb9b4a59d332fa6ec809278 +size 82519