From 3917b123d1c1d63b5366262a6abde676282a3623 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 29 Jun 2022 23:23:37 +1000 Subject: [PATCH] Port Tiff, fix constructors --- src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs | 2 +- src/ImageSharp/Formats/Gif/GifDecoderCore.cs | 7 +-- src/ImageSharp/Formats/Png/PngDecoderCore.cs | 8 +-- .../Formats/Tga/TgaDecoderOptions.cs | 2 +- src/ImageSharp/Formats/Tiff/TiffDecoder.cs | 33 ++++-------- .../Formats/Tiff/TiffDecoderCore.cs | 50 ++++++++++--------- .../Formats/Tiff/TiffDecoderOptions.cs | 14 ++++++ 7 files changed, 63 insertions(+), 53 deletions(-) create mode 100644 src/ImageSharp/Formats/Tiff/TiffDecoderOptions.cs diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs index f00d4cd03b..a9f779bfa6 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs @@ -105,9 +105,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// The options. public BmpDecoderCore(BmpDecoderOptions options) { + this.Options = options; this.configuration = options.GeneralOptions.Configuration; this.memoryAllocator = this.configuration.MemoryAllocator; - this.Options = options; } /// diff --git a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs index c63a3e08ec..c084f57cea 100644 --- a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs @@ -67,7 +67,7 @@ namespace SixLabors.ImageSharp.Formats.Gif private readonly MemoryAllocator memoryAllocator; /// - /// The maximum number of frames to decode. + /// The maximum number of frames to decode. Inclusive. /// private readonly int maxFrames; @@ -92,10 +92,11 @@ namespace SixLabors.ImageSharp.Formats.Gif /// The decoder options. public GifDecoderCore(GifDecoderOptions options) { - this.skipMetadata = options.GeneralOptions.SkipMetadata; + this.Options = options; this.configuration = options.GeneralOptions.Configuration; - this.memoryAllocator = this.configuration.MemoryAllocator; + this.skipMetadata = options.GeneralOptions.SkipMetadata; this.maxFrames = options.GeneralOptions.MaxFrames; + this.memoryAllocator = this.configuration.MemoryAllocator; } /// diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs index ae01a2f568..383a3ffeb3 100644 --- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs @@ -125,17 +125,19 @@ namespace SixLabors.ImageSharp.Formats.Png /// The decoder options. public PngDecoderCore(PngDecoderOptions options) { + this.Options = options; this.configuration = options.GeneralOptions.Configuration; - this.memoryAllocator = this.configuration.MemoryAllocator; this.skipMetadata = options.GeneralOptions.SkipMetadata; + this.memoryAllocator = this.configuration.MemoryAllocator; } internal PngDecoderCore(PngDecoderOptions options, bool colorMetadataOnly) { - this.configuration = options.GeneralOptions.Configuration; - this.memoryAllocator = this.configuration.MemoryAllocator; + this.Options = options; this.colorMetadataOnly = colorMetadataOnly; this.skipMetadata = true; + this.configuration = options.GeneralOptions.Configuration; + this.memoryAllocator = this.configuration.MemoryAllocator; } /// diff --git a/src/ImageSharp/Formats/Tga/TgaDecoderOptions.cs b/src/ImageSharp/Formats/Tga/TgaDecoderOptions.cs index abce31c666..f5c0fb128e 100644 --- a/src/ImageSharp/Formats/Tga/TgaDecoderOptions.cs +++ b/src/ImageSharp/Formats/Tga/TgaDecoderOptions.cs @@ -4,7 +4,7 @@ namespace SixLabors.ImageSharp.Formats.Tga { /// - /// Configuration options for decoding Png images. + /// Configuration options for decoding Tga images. /// public class TgaDecoderOptions : ISpecializedDecoderOptions { diff --git a/src/ImageSharp/Formats/Tiff/TiffDecoder.cs b/src/ImageSharp/Formats/Tiff/TiffDecoder.cs index c4a9f3b225..e503c1af11 100644 --- a/src/ImageSharp/Formats/Tiff/TiffDecoder.cs +++ b/src/ImageSharp/Formats/Tiff/TiffDecoder.cs @@ -3,7 +3,6 @@ using System.IO; using System.Threading; -using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Formats.Tiff @@ -11,39 +10,29 @@ namespace SixLabors.ImageSharp.Formats.Tiff /// /// Image decoder for generating an image out of a TIFF stream. /// - public class TiffDecoder : IImageDecoder, ITiffDecoderOptions, IImageInfoDetector + public class TiffDecoder : ImageDecoder { - /// - /// Gets or sets a value indicating whether the metadata should be ignored when the image is being decoded. - /// - 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, CancellationToken cancellationToken) - where TPixel : unmanaged, IPixel + public override Image DecodeSpecialized(TiffDecoderOptions options, Stream stream, CancellationToken cancellationToken) { - Guard.NotNull(stream, nameof(stream)); + TiffDecoderCore decoder = new(options); + Image image = decoder.Decode(options.GeneralOptions.Configuration, stream, cancellationToken); + + Resize(options.GeneralOptions, image); - var decoder = new TiffDecoderCore(configuration, this); - return decoder.Decode(configuration, stream, cancellationToken); + return image; } /// - public Image Decode(Configuration configuration, Stream stream, CancellationToken cancellationToken) - => this.Decode(configuration, stream, cancellationToken); + public override Image DecodeSpecialized(TiffDecoderOptions options, Stream stream, CancellationToken cancellationToken) + => this.DecodeSpecialized(options, stream, cancellationToken); /// - public IImageInfo Identify(Configuration configuration, Stream stream, CancellationToken cancellationToken) + public override IImageInfo IdentifySpecialized(TiffDecoderOptions options, Stream stream, CancellationToken cancellationToken) { Guard.NotNull(stream, nameof(stream)); - var decoder = new TiffDecoderCore(configuration, this); - return decoder.Identify(configuration, stream, cancellationToken); + return new TiffDecoderCore(options).Identify(options.GeneralOptions.Configuration, stream, cancellationToken); } } } diff --git a/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs b/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs index c595246a5b..0bb01fcdce 100644 --- a/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs +++ b/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs @@ -20,8 +20,13 @@ namespace SixLabors.ImageSharp.Formats.Tiff /// /// Performs the tiff decoding operation. /// - internal class TiffDecoderCore : IImageDecoderInternals + internal class TiffDecoderCore : IImageDecoderInternals { + /// + /// General configuration options. + /// + private readonly Configuration configuration; + /// /// Used for allocating memory during processing operations. /// @@ -30,12 +35,12 @@ namespace SixLabors.ImageSharp.Formats.Tiff /// /// Gets or sets a value indicating whether the metadata should be ignored when the image is being decoded. /// - private readonly bool ignoreMetadata; + private readonly bool skipMetadata; /// - /// Gets the decoding mode for multi-frame images + /// The maximum number of frames to decode. Inclusive. /// - private readonly FrameDecodingMode decodingMode; + private readonly int maxFrames; /// /// The stream to decode from. @@ -55,16 +60,14 @@ namespace SixLabors.ImageSharp.Formats.Tiff /// /// Initializes a new instance of the class. /// - /// The configuration. /// The decoder options. - public TiffDecoderCore(Configuration configuration, ITiffDecoderOptions options) + public TiffDecoderCore(TiffDecoderOptions options) { - options ??= new TiffDecoder(); - - this.Configuration = configuration ?? Configuration.Default; - this.ignoreMetadata = options.IgnoreMetadata; - this.decodingMode = options.DecodingMode; - this.memoryAllocator = this.Configuration.MemoryAllocator; + this.Options = options; + this.configuration = options.GeneralOptions.Configuration; + this.skipMetadata = options.GeneralOptions.SkipMetadata; + this.maxFrames = options.GeneralOptions.MaxFrames; + this.memoryAllocator = this.configuration.MemoryAllocator; } /// @@ -148,7 +151,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff public TiffPredictor Predictor { get; set; } /// - public Configuration Configuration { get; } + public TiffDecoderOptions Options { get; } /// public Size Dimensions { get; private set; } @@ -161,25 +164,26 @@ namespace SixLabors.ImageSharp.Formats.Tiff try { this.inputStream = stream; - var reader = new DirectoryReader(stream, this.Configuration.MemoryAllocator); + var reader = new DirectoryReader(stream, this.configuration.MemoryAllocator); IEnumerable directories = reader.Read(); this.byteOrder = reader.ByteOrder; this.isBigTiff = reader.IsBigTiff; + int frameCount = 0; foreach (ExifProfile ifd in directories) { cancellationToken.ThrowIfCancellationRequested(); ImageFrame frame = this.DecodeFrame(ifd, cancellationToken); frames.Add(frame); - if (this.decodingMode is FrameDecodingMode.First) + if (frameCount++ <= this.maxFrames) { break; } } - ImageMetadata metadata = TiffDecoderMetadataCreator.Create(frames, this.ignoreMetadata, reader.ByteOrder, reader.IsBigTiff); + ImageMetadata metadata = TiffDecoderMetadataCreator.Create(frames, this.skipMetadata, reader.ByteOrder, reader.IsBigTiff); // TODO: Tiff frames can have different sizes. ImageFrame root = frames[0]; @@ -192,7 +196,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff } } - return new Image(this.Configuration, metadata, frames); + return new Image(this.configuration, metadata, frames); } catch { @@ -209,7 +213,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff public IImageInfo Identify(BufferedReadStream stream, CancellationToken cancellationToken) { this.inputStream = stream; - var reader = new DirectoryReader(stream, this.Configuration.MemoryAllocator); + var reader = new DirectoryReader(stream, this.configuration.MemoryAllocator); IEnumerable directories = reader.Read(); ExifProfile rootFrameExifProfile = directories.First(); @@ -233,7 +237,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff where TPixel : unmanaged, IPixel { var imageFrameMetaData = new ImageFrameMetadata(); - if (!this.ignoreMetadata) + if (!this.skipMetadata) { imageFrameMetaData.ExifProfile = tags; } @@ -245,7 +249,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff int width = GetImageWidth(tags); int height = GetImageHeight(tags); - var frame = new ImageFrame(this.Configuration, width, height, imageFrameMetaData); + var frame = new ImageFrame(this.configuration, width, height, imageFrameMetaData); int rowsPerStrip = tags.GetValue(ExifTag.RowsPerStrip) != null ? (int)tags.GetValue(ExifTag.RowsPerStrip).Value : TiffConstants.RowsPerStripInfinity; @@ -369,7 +373,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff } using TiffBaseDecompressor decompressor = TiffDecompressorsFactory.Create( - this.Configuration, + this.configuration, this.CompressionType, this.memoryAllocator, this.PhotometricInterpretation, @@ -449,7 +453,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff Buffer2D pixels = frame.PixelBuffer; using TiffBaseDecompressor decompressor = TiffDecompressorsFactory.Create( - this.Configuration, + this.configuration, this.CompressionType, this.memoryAllocator, this.PhotometricInterpretation, @@ -463,7 +467,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff this.byteOrder); TiffBaseColorDecoder colorDecoder = TiffColorDecoderFactory.Create( - this.Configuration, + this.configuration, this.memoryAllocator, this.ColorType, this.BitsPerSample, diff --git a/src/ImageSharp/Formats/Tiff/TiffDecoderOptions.cs b/src/ImageSharp/Formats/Tiff/TiffDecoderOptions.cs new file mode 100644 index 0000000000..ac01952510 --- /dev/null +++ b/src/ImageSharp/Formats/Tiff/TiffDecoderOptions.cs @@ -0,0 +1,14 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +namespace SixLabors.ImageSharp.Formats.Tiff +{ + /// + /// Configuration options for decoding Tiff images. + /// + public class TiffDecoderOptions : ISpecializedDecoderOptions + { + /// + public DecoderOptions GeneralOptions { get; set; } = new(); + } +}