Browse Source

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

pull/2878/head
Brian Popow 1 year ago
parent
commit
dacb713de3
  1. 148
      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_rgb_96bit_big_endian_deflate_compressed_predictor.tiff
  5. 3
      tests/Images/Input/Tiff/tiled_rgb_96bit_little_endian_deflate_compressed_predictor.tiff

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

@ -72,6 +72,7 @@ internal static class HorizontalPredictor
case TiffColorType.PaletteColor:
UndoGray8BitRow(pixelBytes, width, y);
break;
case TiffColorType.BlackIsZero16:
case TiffColorType.WhiteIsZero16:
if (isBigEndian)
@ -84,6 +85,7 @@ internal static class HorizontalPredictor
}
break;
case TiffColorType.BlackIsZero32:
case TiffColorType.WhiteIsZero32:
if (isBigEndian)
@ -96,14 +98,17 @@ internal static class HorizontalPredictor
}
break;
case TiffColorType.Rgb888:
case TiffColorType.CieLab:
UndoRgb24BitRow(pixelBytes, width, y);
break;
case TiffColorType.Rgba8888:
case TiffColorType.Cmyk:
UndoRgba32BitRow(pixelBytes, width, y);
break;
case TiffColorType.Rgb161616:
if (isBigEndian)
{
@ -115,6 +120,7 @@ internal static class HorizontalPredictor
}
break;
case TiffColorType.Rgba16161616:
if (isBigEndian)
{
@ -125,6 +131,18 @@ internal static class HorizontalPredictor
UndoRgb64BitLittleEndianRow(pixelBytes, width, y);
}
break;
case TiffColorType.Rgb323232:
if (isBigEndian)
{
UndoRgb96BitBigEndianRow(pixelBytes, width, y);
}
else
{
UndoRgb96BitLittleEndianRow(pixelBytes, width, y);
}
break;
}
}
@ -621,6 +639,76 @@ internal static class HorizontalPredictor
}
}
private static void UndoRgb96BitBigEndianRow(Span<byte> pixelBytes, int width, int y)
{
int rowBytesCount = width * 12;
int offset = 0;
Span<byte> rowBytes = pixelBytes.Slice(y * rowBytesCount, rowBytesCount);
uint r = TiffUtilities.ConvertToUIntBigEndian(rowBytes.Slice(offset, 4));
offset += 4;
uint g = TiffUtilities.ConvertToUIntBigEndian(rowBytes.Slice(offset, 4));
offset += 4;
uint b = TiffUtilities.ConvertToUIntBigEndian(rowBytes.Slice(offset, 4));
offset += 4;
for (int x = 1; x < width; x++)
{
Span<byte> rowSpan = rowBytes.Slice(offset, 4);
uint deltaR = TiffUtilities.ConvertToUIntBigEndian(rowSpan);
r += deltaR;
BinaryPrimitives.WriteUInt32BigEndian(rowSpan, r);
offset += 4;
rowSpan = rowBytes.Slice(offset, 4);
uint deltaG = TiffUtilities.ConvertToUIntBigEndian(rowSpan);
g += deltaG;
BinaryPrimitives.WriteUInt32BigEndian(rowSpan, g);
offset += 4;
rowSpan = rowBytes.Slice(offset, 4);
uint deltaB = TiffUtilities.ConvertToUIntBigEndian(rowSpan);
b += deltaB;
BinaryPrimitives.WriteUInt32BigEndian(rowSpan, b);
offset += 4;
}
}
private static void UndoRgb96BitLittleEndianRow(Span<byte> pixelBytes, int width, int y)
{
int rowBytesCount = width * 12;
int offset = 0;
Span<byte> rowBytes = pixelBytes.Slice(y * rowBytesCount, rowBytesCount);
uint r = TiffUtilities.ConvertToUIntLittleEndian(rowBytes.Slice(offset, 4));
offset += 4;
uint g = TiffUtilities.ConvertToUIntLittleEndian(rowBytes.Slice(offset, 4));
offset += 4;
uint b = TiffUtilities.ConvertToUIntLittleEndian(rowBytes.Slice(offset, 4));
offset += 4;
for (int x = 1; x < width; x++)
{
Span<byte> rowSpan = rowBytes.Slice(offset, 4);
uint deltaR = TiffUtilities.ConvertToUIntLittleEndian(rowSpan);
r += deltaR;
BinaryPrimitives.WriteUInt32LittleEndian(rowSpan, r);
offset += 4;
rowSpan = rowBytes.Slice(offset, 4);
uint deltaG = TiffUtilities.ConvertToUIntLittleEndian(rowSpan);
g += deltaG;
BinaryPrimitives.WriteUInt32LittleEndian(rowSpan, g);
offset += 4;
rowSpan = rowBytes.Slice(offset, 4);
uint deltaB = TiffUtilities.ConvertToUIntLittleEndian(rowSpan);
b += deltaB;
BinaryPrimitives.WriteUInt32LittleEndian(rowSpan, b);
offset += 4;
}
}
private static void UndoRgb96Bit(Span<byte> pixelBytes, int width, bool isBigEndian)
{
int rowBytesCount = width * 12;
@ -629,70 +717,14 @@ internal static class HorizontalPredictor
{
for (int y = 0; y < height; y++)
{
int offset = 0;
Span<byte> rowBytes = pixelBytes.Slice(y * rowBytesCount, rowBytesCount);
uint r = TiffUtilities.ConvertToUIntBigEndian(rowBytes.Slice(offset, 4));
offset += 4;
uint g = TiffUtilities.ConvertToUIntBigEndian(rowBytes.Slice(offset, 4));
offset += 4;
uint b = TiffUtilities.ConvertToUIntBigEndian(rowBytes.Slice(offset, 4));
offset += 4;
for (int x = 1; x < width; x++)
{
Span<byte> rowSpan = rowBytes.Slice(offset, 4);
uint deltaR = TiffUtilities.ConvertToUIntBigEndian(rowSpan);
r += deltaR;
BinaryPrimitives.WriteUInt32BigEndian(rowSpan, r);
offset += 4;
rowSpan = rowBytes.Slice(offset, 4);
uint deltaG = TiffUtilities.ConvertToUIntBigEndian(rowSpan);
g += deltaG;
BinaryPrimitives.WriteUInt32BigEndian(rowSpan, g);
offset += 4;
rowSpan = rowBytes.Slice(offset, 4);
uint deltaB = TiffUtilities.ConvertToUIntBigEndian(rowSpan);
b += deltaB;
BinaryPrimitives.WriteUInt32BigEndian(rowSpan, b);
offset += 4;
}
UndoRgb96BitBigEndianRow(pixelBytes, width, y);
}
}
else
{
for (int y = 0; y < height; y++)
{
int offset = 0;
Span<byte> rowBytes = pixelBytes.Slice(y * rowBytesCount, rowBytesCount);
uint r = TiffUtilities.ConvertToUIntLittleEndian(rowBytes.Slice(offset, 4));
offset += 4;
uint g = TiffUtilities.ConvertToUIntLittleEndian(rowBytes.Slice(offset, 4));
offset += 4;
uint b = TiffUtilities.ConvertToUIntLittleEndian(rowBytes.Slice(offset, 4));
offset += 4;
for (int x = 1; x < width; x++)
{
Span<byte> rowSpan = rowBytes.Slice(offset, 4);
uint deltaR = TiffUtilities.ConvertToUIntLittleEndian(rowSpan);
r += deltaR;
BinaryPrimitives.WriteUInt32LittleEndian(rowSpan, r);
offset += 4;
rowSpan = rowBytes.Slice(offset, 4);
uint deltaG = TiffUtilities.ConvertToUIntLittleEndian(rowSpan);
g += deltaG;
BinaryPrimitives.WriteUInt32LittleEndian(rowSpan, g);
offset += 4;
rowSpan = rowBytes.Slice(offset, 4);
uint deltaB = TiffUtilities.ConvertToUIntLittleEndian(rowSpan);
b += deltaB;
BinaryPrimitives.WriteUInt32LittleEndian(rowSpan, b);
offset += 4;
}
UndoRgb96BitLittleEndianRow(pixelBytes, width, y);
}
}
}

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

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

2
tests/ImageSharp.Tests/TestImages.cs

@ -997,6 +997,8 @@ public static class TestImages
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";
public const string TiledRgb96BitLittleEndianDeflateCompressedWithPredictor = "Tiff/tiled_rgb_96bit_little_endian_deflate_compressed_predictor.tiff";
public const string TiledRgb96BitBigEndianDeflateCompressedWithPredictor = "Tiff/tiled_rgb_96bit_big_endian_deflate_compressed_predictor.tiff";
// Images with alpha channel.
public const string Rgba2BitUnassociatedAlpha = "Tiff/RgbaUnassociatedAlpha2bit.tiff";

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

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

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

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