diff --git a/src/ImageSharp/Formats/Gif/GifDecoder.cs b/src/ImageSharp/Formats/Gif/GifDecoder.cs index 196d77ad77..c31a2c1c94 100644 --- a/src/ImageSharp/Formats/Gif/GifDecoder.cs +++ b/src/ImageSharp/Formats/Gif/GifDecoder.cs @@ -5,7 +5,6 @@ using System.Threading; using System.Threading.Tasks; using SixLabors.ImageSharp.IO; -using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.PixelFormats; diff --git a/src/ImageSharp/Formats/Tiff/ITiffDecoderOptions.cs b/src/ImageSharp/Formats/Tiff/ITiffDecoderOptions.cs index 5372384397..d6d1bb8a4c 100644 --- a/src/ImageSharp/Formats/Tiff/ITiffDecoderOptions.cs +++ b/src/ImageSharp/Formats/Tiff/ITiffDecoderOptions.cs @@ -1,6 +1,8 @@ // Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. +using SixLabors.ImageSharp.Metadata; + namespace SixLabors.ImageSharp.Formats.Tiff { /// @@ -12,5 +14,10 @@ internal interface ITiffDecoderOptions /// Gets a value indicating whether the metadata should be ignored when the image is being decoded. /// bool IgnoreMetadata { get; } + + /// + /// Gets the decoding mode for multi-frame images. + /// + FrameDecodingMode DecodingMode { get; } } } diff --git a/src/ImageSharp/Formats/Tiff/README.md b/src/ImageSharp/Formats/Tiff/README.md index 488701e318..51e84ef558 100644 --- a/src/ImageSharp/Formats/Tiff/README.md +++ b/src/ImageSharp/Formats/Tiff/README.md @@ -25,7 +25,7 @@ ## Implementation Status -- The Decoder currently only supports a single frame per image. +- The Decoder currently only supports decoding multiframe images, which have the same dimensions. - Some compression formats are not yet supported. See the list below. ### Deviations from the TIFF spec (to be fixed) diff --git a/src/ImageSharp/Formats/Tiff/TiffDecoder.cs b/src/ImageSharp/Formats/Tiff/TiffDecoder.cs index 9d52e34dfe..b4d7520199 100644 --- a/src/ImageSharp/Formats/Tiff/TiffDecoder.cs +++ b/src/ImageSharp/Formats/Tiff/TiffDecoder.cs @@ -4,6 +4,7 @@ using System.IO; using System.Threading; using System.Threading.Tasks; +using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Formats.Tiff @@ -18,6 +19,11 @@ public class TiffDecoder : IImageDecoder, ITiffDecoderOptions, IImageInfoDetecto /// public bool IgnoreMetadata { get; set; } + /// + /// Gets or sets the decoding mode for multi-frame images. + /// + public FrameDecodingMode DecodingMode { get; set; } + /// public Image Decode(Configuration configuration, Stream stream) where TPixel : unmanaged, IPixel diff --git a/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs b/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs index 05c5358f59..cd06282f18 100644 --- a/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs +++ b/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs @@ -13,7 +13,6 @@ using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.Metadata.Profiles.Exif; -using SixLabors.ImageSharp.Metadata.Profiles.Xmp; using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Formats.Tiff @@ -33,6 +32,11 @@ internal class TiffDecoderCore : IImageDecoderInternals /// private readonly bool ignoreMetadata; + /// + /// Gets the decoding mode for multi-frame images + /// + private FrameDecodingMode decodingMode; + /// /// The stream to decode from. /// @@ -59,6 +63,7 @@ public TiffDecoderCore(Configuration configuration, ITiffDecoderOptions options) this.Configuration = configuration ?? Configuration.Default; this.ignoreMetadata = options.IgnoreMetadata; + this.decodingMode = options.DecodingMode; this.memoryAllocator = this.Configuration.MemoryAllocator; } @@ -160,11 +165,16 @@ public Image Decode(BufferedReadStream stream, CancellationToken cancellationToken.ThrowIfCancellationRequested(); ImageFrame frame = this.DecodeFrame(ifd, cancellationToken); frames.Add(frame); + + if (this.decodingMode is FrameDecodingMode.First) + { + break; + } } ImageMetadata metadata = TiffDecoderMetadataCreator.Create(frames, this.ignoreMetadata, reader.ByteOrder, reader.IsBigTiff); - // TODO: Tiff frames can have different sizes + // TODO: Tiff frames can have different sizes. ImageFrame root = frames[0]; this.Dimensions = root.Size(); foreach (ImageFrame frame in frames) diff --git a/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs index 2748900668..e4f4d26b85 100644 --- a/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs @@ -4,6 +4,7 @@ // ReSharper disable InconsistentNaming using System; using System.IO; +using SixLabors.ImageSharp.Formats.Tiff; using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; @@ -365,6 +366,17 @@ public void TiffDecoder_CanDecode_Compressed_LowerOrderBitsFirst(TestIma public void TiffDecoder_CanDecode_PackBitsCompressed(TestImageProvider provider) where TPixel : unmanaged, IPixel => TestTiffDecoder(provider); + [Theory] + [WithFile(MultiFrameMipMap, PixelTypes.Rgba32)] + public void CanDecodeJustOneFrame(TestImageProvider provider) + where TPixel : unmanaged, IPixel + { + using (Image image = provider.GetImage(new TiffDecoder() { DecodingMode = FrameDecodingMode.First })) + { + Assert.Equal(1, image.Frames.Count); + } + } + [Theory] [WithFile(RgbJpegCompressed, PixelTypes.Rgba32)] [WithFile(RgbWithStripsJpegCompressed, PixelTypes.Rgba32)] diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 4830a43083..7ae0ac6e20 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -874,6 +874,7 @@ public static class Tiff public const string MultiframeDeflateWithPreview = "Tiff/multipage_deflate_withPreview.tiff"; public const string MultiframeDifferentSize = "Tiff/multipage_differentSize.tiff"; public const string MultiframeDifferentVariants = "Tiff/multipage_differentVariants.tiff"; + public const string MultiFrameMipMap = "Tiff/SKC1H3.tiff"; public const string LittleEndianByteOrder = "Tiff/little_endian.tiff"; diff --git a/tests/Images/Input/Tiff/SKC1H3.tiff b/tests/Images/Input/Tiff/SKC1H3.tiff new file mode 100644 index 0000000000..9f9a50fdd6 --- /dev/null +++ b/tests/Images/Input/Tiff/SKC1H3.tiff @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:938bbf1c0f8bdbea0c632bb8d51c1150f757f88b3779d7fa18c296a3a3f61e9b +size 13720193