Browse Source

Add support for horizontal predictor with 32 bit color tiff's

pull/1729/head
Brian Popow 5 years ago
parent
commit
f8f0c101c8
  1. 79
      src/ImageSharp/Formats/Tiff/Compression/HorizontalPredictor.cs
  2. 11
      tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs
  3. 2
      tests/ImageSharp.Tests/TestImages.cs
  4. 3
      tests/Images/Input/Tiff/flower-rgb-contig-32_lsb_zip_predictor.tiff
  5. 3
      tests/Images/Input/Tiff/flower-rgb-contig-32_msb_zip_predictor.tiff

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

@ -46,6 +46,9 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression
case TiffColorType.Rgb161616:
UndoRgb48Bit(pixelBytes, width, isBigEndian);
break;
case TiffColorType.Rgb323232:
UndoRgb96Bit(pixelBytes, width, isBigEndian);
break;
}
}
@ -315,5 +318,81 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression
}
}
}
private static void UndoRgb96Bit(Span<byte> pixelBytes, int width, bool isBigEndian)
{
int rowBytesCount = width * 12;
int height = pixelBytes.Length / rowBytesCount;
if (isBigEndian)
{
for (int y = 0; y < height; y++)
{
int offset = 0;
Span<byte> rowBytes = pixelBytes.Slice(y * rowBytesCount, rowBytesCount);
uint r = TiffUtils.ConvertToUIntBigEndian(rowBytes.Slice(offset, 4));
offset += 4;
uint g = TiffUtils.ConvertToUIntBigEndian(rowBytes.Slice(offset, 4));
offset += 4;
uint b = TiffUtils.ConvertToUIntBigEndian(rowBytes.Slice(offset, 4));
offset += 4;
for (int x = 1; x < width; x++)
{
Span<byte> rowSpan = rowBytes.Slice(offset, 4);
uint deltaR = TiffUtils.ConvertToUIntBigEndian(rowSpan);
r += deltaR;
BinaryPrimitives.WriteUInt32BigEndian(rowSpan, r);
offset += 4;
rowSpan = rowBytes.Slice(offset, 4);
uint deltaG = TiffUtils.ConvertToUIntBigEndian(rowSpan);
g += deltaG;
BinaryPrimitives.WriteUInt32BigEndian(rowSpan, g);
offset += 4;
rowSpan = rowBytes.Slice(offset, 4);
uint deltaB = TiffUtils.ConvertToUIntBigEndian(rowSpan);
b += deltaB;
BinaryPrimitives.WriteUInt32BigEndian(rowSpan, b);
offset += 4;
}
}
}
else
{
for (int y = 0; y < height; y++)
{
int offset = 0;
Span<byte> rowBytes = pixelBytes.Slice(y * rowBytesCount, rowBytesCount);
uint r = TiffUtils.ConvertToUIntLittleEndian(rowBytes.Slice(offset, 4));
offset += 4;
uint g = TiffUtils.ConvertToUIntLittleEndian(rowBytes.Slice(offset, 4));
offset += 4;
uint b = TiffUtils.ConvertToUIntLittleEndian(rowBytes.Slice(offset, 4));
offset += 4;
for (int x = 1; x < width; x++)
{
Span<byte> rowSpan = rowBytes.Slice(offset, 4);
uint deltaR = TiffUtils.ConvertToUIntLittleEndian(rowSpan);
r += deltaR;
BinaryPrimitives.WriteUInt32LittleEndian(rowSpan, r);
offset += 4;
rowSpan = rowBytes.Slice(offset, 4);
uint deltaG = TiffUtils.ConvertToUIntLittleEndian(rowSpan);
g += deltaG;
BinaryPrimitives.WriteUInt32LittleEndian(rowSpan, g);
offset += 4;
rowSpan = rowBytes.Slice(offset, 4);
uint deltaB = TiffUtils.ConvertToUIntLittleEndian(rowSpan);
b += deltaB;
BinaryPrimitives.WriteUInt32LittleEndian(rowSpan, b);
offset += 4;
}
}
}
}
}
}

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

@ -260,6 +260,17 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
image.DebugSave(provider);
}
[Theory]
[WithFile(FlowerRgb323232PredictorBigEndian, PixelTypes.Rgba32)]
[WithFile(FlowerRgb323232PredictorLittleEndian, PixelTypes.Rgba32)]
public void TiffDecoder_CanDecode_96Bit_WithPredictor<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
// Note: because the MagickReferenceDecoder fails to load the image, we only debug save them.
using Image<TPixel> image = provider.GetImage();
image.DebugSave(provider);
}
[Theory]
[WithFile(GrayscaleDeflateMultistrip, PixelTypes.Rgba32)]
[WithFile(RgbDeflateMultistrip, PixelTypes.Rgba32)]

2
tests/ImageSharp.Tests/TestImages.cs

@ -567,6 +567,8 @@ namespace SixLabors.ImageSharp.Tests
public const string FlowerRgb323232ContiguousLittleEndian = "Tiff/flower-rgb-contig-32_lsb.tiff";
public const string FlowerRgb323232Planar = "Tiff/flower-rgb-planar-32.tiff";
public const string FlowerRgb323232PlanarLittleEndian = "Tiff/flower-rgb-planar-32_lsb.tiff";
public const string FlowerRgb323232PredictorBigEndian = "Tiff/flower-rgb-contig-32_msb_zip_predictor.tiff";
public const string FlowerRgb323232PredictorLittleEndian = "Tiff/flower-rgb-contig-32_lsb_zip_predictor.tiff";
public const string FlowerRgb242424Planar = "Tiff/flower-rgb-planar-24.tiff";
public const string FlowerRgb242424PlanarLittleEndian = "Tiff/flower-rgb-planar-24_lsb.tiff";
public const string FlowerRgb242424Contiguous = "Tiff/flower-rgb-contig-24.tiff";

3
tests/Images/Input/Tiff/flower-rgb-contig-32_lsb_zip_predictor.tiff

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

3
tests/Images/Input/Tiff/flower-rgb-contig-32_msb_zip_predictor.tiff

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