diff --git a/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs b/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs index 942e510d34..806d563344 100644 --- a/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs +++ b/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs @@ -208,6 +208,25 @@ namespace ImageSharp.Formats Image image = new Image(this.configuration, width, height); + this.ReadMetadata(ifd, image); + this.ReadImageFormat(ifd); + + if (ifd.TryGetIfdEntry(TiffTags.RowsPerStrip, out TiffIfdEntry rowsPerStripEntry) + && ifd.TryGetIfdEntry(TiffTags.StripOffsets, out TiffIfdEntry stripOffsetsEntry) + && ifd.TryGetIfdEntry(TiffTags.StripByteCounts, out TiffIfdEntry stripByteCountsEntry)) + { + int rowsPerStrip = (int)this.ReadUnsignedInteger(ref rowsPerStripEntry); + uint[] stripOffsets = this.ReadUnsignedIntegerArray(ref stripOffsetsEntry); + uint[] stripByteCounts = this.ReadUnsignedIntegerArray(ref stripByteCountsEntry); + this.DecodeImageStrips(image, rowsPerStrip, stripOffsets, stripByteCounts); + } + + return image; + } + + public void ReadMetadata(TiffIfd ifd, Image image) + where TPixel : struct, IPixel + { TiffResolutionUnit resolutionUnit = (TiffResolutionUnit)this.ReadUnsignedInteger(ifd, TiffTags.ResolutionUnit, (uint)TiffResolutionUnit.Inch); if (resolutionUnit != TiffResolutionUnit.None) @@ -226,20 +245,6 @@ namespace ImageSharp.Formats image.MetaData.VerticalResolution = yResolution.ToDouble() * resolutionUnitFactor; } } - - this.ReadImageFormat(ifd); - - if (ifd.TryGetIfdEntry(TiffTags.RowsPerStrip, out TiffIfdEntry rowsPerStripEntry) - && ifd.TryGetIfdEntry(TiffTags.StripOffsets, out TiffIfdEntry stripOffsetsEntry) - && ifd.TryGetIfdEntry(TiffTags.StripByteCounts, out TiffIfdEntry stripByteCountsEntry)) - { - int rowsPerStrip = (int)this.ReadUnsignedInteger(ref rowsPerStripEntry); - uint[] stripOffsets = this.ReadUnsignedIntegerArray(ref stripOffsetsEntry); - uint[] stripByteCounts = this.ReadUnsignedIntegerArray(ref stripByteCountsEntry); - this.DecodeImageStrips(image, rowsPerStrip, stripOffsets, stripByteCounts); - } - - return image; } /// diff --git a/tests/ImageSharp.Formats.Tiff.Tests/Formats/Tiff/TiffDecoderImageTests.cs b/tests/ImageSharp.Formats.Tiff.Tests/Formats/Tiff/TiffDecoderImageTests.cs index 9f90e691d2..3d6cf355ac 100644 --- a/tests/ImageSharp.Formats.Tiff.Tests/Formats/Tiff/TiffDecoderImageTests.cs +++ b/tests/ImageSharp.Formats.Tiff.Tests/Formats/Tiff/TiffDecoderImageTests.cs @@ -16,8 +16,6 @@ namespace ImageSharp.Tests { public const int ImageWidth = 200; public const int ImageHeight = 150; - public const int XResolution = 100; - public const int YResolution = 200; public static object[][] IsLittleEndianValues = new[] { new object[] { false }, new object[] { true } }; @@ -37,57 +35,6 @@ namespace ImageSharp.Tests Assert.Equal(ImageHeight, image.Height); } - [Theory] - [InlineData(false, 150u, 1u, 200u, 1u, 2u /* Inch */, 150.0, 200.0)] - [InlineData(false, 150u, 1u, 200u, 1u, 3u /* Cm */, 150.0 * 2.54, 200.0 * 2.54)] - [InlineData(false, 150u, 1u, 200u, 1u, 1u /* None */, 96.0, 96.0)] - [InlineData(false, 150u, 1u, 200u, 1u, null /* Inch */, 150.0, 200.0)] - [InlineData(false, 5u, 2u, 9u, 4u, 2u /* Inch */, 2.5, 2.25)] - [InlineData(false, null, null, null, null, null /* Inch */, 96.0, 96.0)] - [InlineData(false, 150u, 1u, null, null, 2u /* Inch */, 150.0, 96.0)] - [InlineData(false, null, null, 200u, 1u, 2u /* Inch */, 96.0, 200.0)] - [InlineData(true, 150u, 1u, 200u, 1u, 2u /* Inch */, 150.0, 200.0)] - [InlineData(true, 150u, 1u, 200u, 1u, 3u /* Cm */, 150.0 * 2.54, 200.0 * 2.54)] - [InlineData(true, 150u, 1u, 200u, 1u, 1u /* None */, 96.0, 96.0)] - [InlineData(true, 5u, 2u, 9u, 4u, 2u /* Inch */, 2.5, 2.25)] - [InlineData(true, 150u, 1u, 200u, 1u, null /* Inch */, 150.0, 200.0)] - [InlineData(true, null, null, null, null, null /* Inch */, 96.0, 96.0)] - [InlineData(true, 150u, 1u, null, null, 2u /* Inch */, 150.0, 96.0)] - [InlineData(true, null, null, 200u, 1u, 2u /* Inch */, 96.0, 200.0)] - public void DecodeImage_SetsImageResolution(bool isLittleEndian, uint? xResolutionNumerator, uint? xResolutionDenominator, - uint? yResolutionNumerator, uint? yResolutionDenominator, uint? resolutionUnit, - double expectedHorizonalResolution, double expectedVerticalResolution) - { - TiffGenIfd ifdGen = CreateTiffGenIfd() - .WithoutEntry(TiffTags.XResolution) - .WithoutEntry(TiffTags.YResolution) - .WithoutEntry(TiffTags.ResolutionUnit); - - if (xResolutionNumerator != null) - { - ifdGen.WithEntry(TiffGenEntry.Rational(TiffTags.XResolution, xResolutionNumerator.Value, xResolutionDenominator.Value)); - } - - if (yResolutionNumerator != null) - { - ifdGen.WithEntry(TiffGenEntry.Rational(TiffTags.YResolution, yResolutionNumerator.Value, yResolutionDenominator.Value)); - } - - if (resolutionUnit != null) - { - ifdGen.WithEntry(TiffGenEntry.Integer(TiffTags.ResolutionUnit, TiffType.Short, resolutionUnit.Value)); - } - - Stream stream = ifdGen.ToStream(isLittleEndian); - - TiffDecoderCore decoder = new TiffDecoderCore(stream, isLittleEndian, null, null); - TiffIfd ifd = decoder.ReadIfd(0); - Image image = decoder.DecodeImage(ifd); - - Assert.Equal(expectedHorizonalResolution, image.MetaData.HorizontalResolution, 10); - Assert.Equal(expectedVerticalResolution, image.MetaData.VerticalResolution, 10); - } - [Theory] [MemberData(nameof(IsLittleEndianValues))] public void DecodeImage_ThrowsException_WithMissingImageWidth(bool isLittleEndian) @@ -551,8 +498,8 @@ namespace ImageSharp.Tests { TiffGenEntry.Integer(TiffTags.ImageWidth, TiffType.Long, ImageWidth), TiffGenEntry.Integer(TiffTags.ImageLength, TiffType.Long, ImageHeight), - TiffGenEntry.Rational(TiffTags.XResolution, XResolution, 1), - TiffGenEntry.Rational(TiffTags.YResolution, YResolution, 1), + TiffGenEntry.Rational(TiffTags.XResolution, 100, 1), + TiffGenEntry.Rational(TiffTags.YResolution, 200, 1), TiffGenEntry.Integer(TiffTags.ResolutionUnit, TiffType.Short, 2), TiffGenEntry.Integer(TiffTags.PhotometricInterpretation, TiffType.Short, (int)TiffPhotometricInterpretation.WhiteIsZero), TiffGenEntry.Integer(TiffTags.BitsPerSample, TiffType.Short, new int[] { 8 }), diff --git a/tests/ImageSharp.Formats.Tiff.Tests/Formats/Tiff/TiffDecoderMetadataTests.cs b/tests/ImageSharp.Formats.Tiff.Tests/Formats/Tiff/TiffDecoderMetadataTests.cs new file mode 100644 index 0000000000..b3dd30f5e3 --- /dev/null +++ b/tests/ImageSharp.Formats.Tiff.Tests/Formats/Tiff/TiffDecoderMetadataTests.cs @@ -0,0 +1,70 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Tests +{ + using System; + using System.IO; + using Xunit; + + using ImageSharp.Formats; + using ImageSharp.Formats.Tiff; + + public class TiffDecoderMetadataTests + { + public static object[][] IsLittleEndianValues = new[] { new object[] { false }, + new object[] { true } }; + + [Theory] + [InlineData(false, 150u, 1u, 200u, 1u, 2u /* Inch */, 150.0, 200.0)] + [InlineData(false, 150u, 1u, 200u, 1u, 3u /* Cm */, 150.0 * 2.54, 200.0 * 2.54)] + [InlineData(false, 150u, 1u, 200u, 1u, 1u /* None */, 96.0, 96.0)] + [InlineData(false, 150u, 1u, 200u, 1u, null /* Inch */, 150.0, 200.0)] + [InlineData(false, 5u, 2u, 9u, 4u, 2u /* Inch */, 2.5, 2.25)] + [InlineData(false, null, null, null, null, null /* Inch */, 96.0, 96.0)] + [InlineData(false, 150u, 1u, null, null, 2u /* Inch */, 150.0, 96.0)] + [InlineData(false, null, null, 200u, 1u, 2u /* Inch */, 96.0, 200.0)] + [InlineData(true, 150u, 1u, 200u, 1u, 2u /* Inch */, 150.0, 200.0)] + [InlineData(true, 150u, 1u, 200u, 1u, 3u /* Cm */, 150.0 * 2.54, 200.0 * 2.54)] + [InlineData(true, 150u, 1u, 200u, 1u, 1u /* None */, 96.0, 96.0)] + [InlineData(true, 5u, 2u, 9u, 4u, 2u /* Inch */, 2.5, 2.25)] + [InlineData(true, 150u, 1u, 200u, 1u, null /* Inch */, 150.0, 200.0)] + [InlineData(true, null, null, null, null, null /* Inch */, 96.0, 96.0)] + [InlineData(true, 150u, 1u, null, null, 2u /* Inch */, 150.0, 96.0)] + [InlineData(true, null, null, 200u, 1u, 2u /* Inch */, 96.0, 200.0)] + public void DecodeImage_SetsImageResolution(bool isLittleEndian, uint? xResolutionNumerator, uint? xResolutionDenominator, + uint? yResolutionNumerator, uint? yResolutionDenominator, uint? resolutionUnit, + double expectedHorizonalResolution, double expectedVerticalResolution) + { + TiffGenIfd ifdGen = new TiffGenIfd(); + + if (xResolutionNumerator != null) + { + ifdGen.WithEntry(TiffGenEntry.Rational(TiffTags.XResolution, xResolutionNumerator.Value, xResolutionDenominator.Value)); + } + + if (yResolutionNumerator != null) + { + ifdGen.WithEntry(TiffGenEntry.Rational(TiffTags.YResolution, yResolutionNumerator.Value, yResolutionDenominator.Value)); + } + + if (resolutionUnit != null) + { + ifdGen.WithEntry(TiffGenEntry.Integer(TiffTags.ResolutionUnit, TiffType.Short, resolutionUnit.Value)); + } + + Stream stream = ifdGen.ToStream(isLittleEndian); + + TiffDecoderCore decoder = new TiffDecoderCore(stream, isLittleEndian, null, null); + TiffIfd ifd = decoder.ReadIfd(0); + Image image = new Image(null, 20, 20); + + decoder.ReadMetadata(ifd, image); + + Assert.Equal(expectedHorizonalResolution, image.MetaData.HorizontalResolution, 10); + Assert.Equal(expectedVerticalResolution, image.MetaData.VerticalResolution, 10); + } + } +} \ No newline at end of file