diff --git a/src/ImageSharp/Advanced/AotCompilerTools.cs b/src/ImageSharp/Advanced/AotCompilerTools.cs index 7db2b7f96..5e8b899a4 100644 --- a/src/ImageSharp/Advanced/AotCompilerTools.cs +++ b/src/ImageSharp/Advanced/AotCompilerTools.cs @@ -178,7 +178,7 @@ namespace SixLabors.ImageSharp.Advanced img.CloneAs(default); img.CloneAs(default); - ImageFrame.LoadPixelData(default, default(ReadOnlySpan), default, default); + ImageFrame.LoadPixelData(default, default(ReadOnlySpan), default, default); ImageFrame.LoadPixelData(default, default(ReadOnlySpan), default, default); } @@ -210,21 +210,21 @@ namespace SixLabors.ImageSharp.Advanced } /// - /// This method pre-seeds the all in the AoT compiler. + /// This method pre-seeds the all in the AoT compiler. /// /// The pixel format. [Preserve] private static void AotCompileImageDecoderInternals() where TPixel : unmanaged, IPixel { - default(WebpDecoderCore).Decode(default, default, default); - default(BmpDecoderCore).Decode(default, default, default); - default(GifDecoderCore).Decode(default, default, default); - default(JpegDecoderCore).Decode(default, default, default); - default(PbmDecoderCore).Decode(default, default, default); - default(PngDecoderCore).Decode(default, default, default); - default(TgaDecoderCore).Decode(default, default, default); - default(TiffDecoderCore).Decode(default, default, default); + default(WebpDecoderCore).Decode(default, default); + default(BmpDecoderCore).Decode(default, default); + default(GifDecoderCore).Decode(default, default); + default(JpegDecoderCore).Decode(default, default); + default(PbmDecoderCore).Decode(default, default); + default(PngDecoderCore).Decode(default, default); + default(TgaDecoderCore).Decode(default, default); + default(TiffDecoderCore).Decode(default, default); } /// @@ -286,9 +286,7 @@ namespace SixLabors.ImageSharp.Advanced private static void AotCompileImageDecoder() where TPixel : unmanaged, IPixel where TDecoder : class, IImageDecoder - { - default(TDecoder).Decode(default, default, default); - } + => default(TDecoder).Decode(default, default, default); /// /// This method pre-seeds the all in the AoT compiler. diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderOptions.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderOptions.cs index 535f819d2..b01d17980 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoderOptions.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoderOptions.cs @@ -1,5 +1,5 @@ // Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. +// Licensed under the Six Labors Split License. namespace SixLabors.ImageSharp.Formats.Bmp { diff --git a/src/ImageSharp/Formats/DecoderOptions.cs b/src/ImageSharp/Formats/DecoderOptions.cs index 95b02a0ae..5e03efb6e 100644 --- a/src/ImageSharp/Formats/DecoderOptions.cs +++ b/src/ImageSharp/Formats/DecoderOptions.cs @@ -1,5 +1,5 @@ // Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. +// Licensed under the Six Labors Split License. using System; @@ -10,8 +10,15 @@ namespace SixLabors.ImageSharp.Formats /// public sealed class DecoderOptions { + private static readonly Lazy LazyOptions = new(() => new()); + private uint maxFrames = int.MaxValue; + /// + /// Gets the shared default general decoder options instance. + /// + public static DecoderOptions Default { get; } = LazyOptions.Value; + /// /// Gets or sets a custom Configuration instance to be used by the image processing pipeline. /// diff --git a/src/ImageSharp/Formats/Gif/GifDecoderOptions.cs b/src/ImageSharp/Formats/Gif/GifDecoderOptions.cs index 429c1fee1..3c5f7bddc 100644 --- a/src/ImageSharp/Formats/Gif/GifDecoderOptions.cs +++ b/src/ImageSharp/Formats/Gif/GifDecoderOptions.cs @@ -1,5 +1,5 @@ // Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. +// Licensed under the Six Labors Split License. namespace SixLabors.ImageSharp.Formats.Gif { diff --git a/src/ImageSharp/Formats/IImageDecoder.cs b/src/ImageSharp/Formats/IImageDecoder.cs index 82c7804d5..cdec1e928 100644 --- a/src/ImageSharp/Formats/IImageDecoder.cs +++ b/src/ImageSharp/Formats/IImageDecoder.cs @@ -16,22 +16,22 @@ namespace SixLabors.ImageSharp.Formats /// Decodes the image from the specified stream to an of a specific pixel type. /// /// The pixel format. - /// The configuration for the image. + /// The general decoder options. /// The containing image data. /// The token to monitor for cancellation requests. /// The . - // TODO: Document ImageFormatExceptions (https://github.com/SixLabors/ImageSharp/issues/1110) - Image Decode(Configuration configuration, Stream stream, CancellationToken cancellationToken) + /// Thrown if the encoded image contains errors. + Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) where TPixel : unmanaged, IPixel; /// /// Decodes the image from the specified stream to an . /// - /// The configuration for the image. + /// The general decoder options. /// The containing image data. /// The token to monitor for cancellation requests. /// The . - // TODO: Document ImageFormatExceptions (https://github.com/SixLabors/ImageSharp/issues/1110) - Image Decode(Configuration configuration, Stream stream, CancellationToken cancellationToken); + /// Thrown if the encoded image contains errors. + Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken); } } diff --git a/src/ImageSharp/Formats/IImageDecoder2.cs b/src/ImageSharp/Formats/IImageDecoder2.cs deleted file mode 100644 index 76d1a754d..000000000 --- a/src/ImageSharp/Formats/IImageDecoder2.cs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -using System.IO; -using System.Threading; -using SixLabors.ImageSharp.PixelFormats; - -namespace SixLabors.ImageSharp.Formats -{ - /// - /// Encapsulates properties and methods required for decoding an image from a stream. - /// - public interface IImageDecoder2 - { - /// - /// Decodes the image from the specified stream to an of a specific pixel type. - /// - /// The pixel format. - /// The general decoder options. - /// The containing image data. - /// The token to monitor for cancellation requests. - /// The . - /// Thrown if the encoded image contains errors. - Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) - where TPixel : unmanaged, IPixel; - - /// - /// Decodes the image from the specified stream to an . - /// - /// The general decoder options. - /// The containing image data. - /// The token to monitor for cancellation requests. - /// The . - /// Thrown if the encoded image contains errors. - Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken); - } -} diff --git a/src/ImageSharp/Formats/IImageInfoDetector.cs b/src/ImageSharp/Formats/IImageInfoDetector.cs index 2d30af5ce..443e8b980 100644 --- a/src/ImageSharp/Formats/IImageInfoDetector.cs +++ b/src/ImageSharp/Formats/IImageInfoDetector.cs @@ -14,10 +14,11 @@ namespace SixLabors.ImageSharp.Formats /// /// Reads the raw image information from the specified stream. /// - /// The configuration for the image. + /// The general decoder options. /// The containing image data. /// The token to monitor for cancellation requests. - /// The object - IImageInfo Identify(Configuration configuration, Stream stream, CancellationToken cancellationToken); + /// The object. + /// Thrown if the encoded image contains errors. + IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken); } } diff --git a/src/ImageSharp/Formats/IImageInfoDetector2.cs b/src/ImageSharp/Formats/IImageInfoDetector2.cs deleted file mode 100644 index 3d340f06e..000000000 --- a/src/ImageSharp/Formats/IImageInfoDetector2.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -using System.IO; -using System.Threading; - -namespace SixLabors.ImageSharp.Formats -{ - /// - /// Encapsulates methods used for detecting the raw image information without fully decoding it. - /// - public interface IImageInfoDetector2 - { - /// - /// Reads the raw image information from the specified stream. - /// - /// The general decoder options. - /// The containing image data. - /// The token to monitor for cancellation requests. - /// The object. - /// Thrown if the encoded image contains errors. - IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken); - } -} diff --git a/src/ImageSharp/Formats/ISpecializedDecoderOptions.cs b/src/ImageSharp/Formats/ISpecializedDecoderOptions.cs index b79938f08..eacb90183 100644 --- a/src/ImageSharp/Formats/ISpecializedDecoderOptions.cs +++ b/src/ImageSharp/Formats/ISpecializedDecoderOptions.cs @@ -1,5 +1,5 @@ // Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. +// Licensed under the Six Labors Split License. namespace SixLabors.ImageSharp.Formats { diff --git a/src/ImageSharp/Formats/ImageDecoder{T}.cs b/src/ImageSharp/Formats/ImageDecoder{T}.cs index 96080b3be..3a7559579 100644 --- a/src/ImageSharp/Formats/ImageDecoder{T}.cs +++ b/src/ImageSharp/Formats/ImageDecoder{T}.cs @@ -1,5 +1,5 @@ // Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. +// Licensed under the Six Labors Split License. using System.IO; using System.Threading; @@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.Formats /// The base class for all image decoders. /// /// The type of specialized decoder options. - public abstract class ImageDecoder : IImageInfoDetector2, IImageDecoder2 + public abstract class ImageDecoder : IImageInfoDetector, IImageDecoder where T : ISpecializedDecoderOptions, new() { /// diff --git a/src/ImageSharp/Formats/Jpeg/IJpegDecoderOptions.cs b/src/ImageSharp/Formats/Jpeg/IJpegDecoderOptions.cs deleted file mode 100644 index 76874b7ff..000000000 --- a/src/ImageSharp/Formats/Jpeg/IJpegDecoderOptions.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Six Labors Split License. - -namespace SixLabors.ImageSharp.Formats.Jpeg -{ - /// - /// Image decoder for generating an image out of a jpg stream. - /// - internal interface IJpegDecoderOptions - { - /// - /// Gets a value indicating whether the metadata should be ignored when the image is being decoded. - /// - bool IgnoreMetadata { get; } - } -} diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs index 7f23d1ac8..1675fd6d7 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs @@ -3,77 +3,45 @@ using System.IO; using System.Threading; -using SixLabors.ImageSharp.IO; -using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Formats.Jpeg { /// - /// Image decoder for generating an image out of a jpg stream. + /// Decoder for generating an image out of a jpeg encoded stream. /// - public sealed class JpegDecoder : IImageDecoder, IJpegDecoderOptions, IImageInfoDetector + public sealed class JpegDecoder : ImageDecoder { /// - public bool IgnoreMetadata { get; set; } - - /// - public Image Decode(Configuration configuration, Stream stream, CancellationToken cancellationToken) - where TPixel : unmanaged, IPixel + /// + /// Unlike , when + /// is passed, the codec may not be able to scale efficiently to + /// the exact scale factor requested, so returns a size that approximates that scale. + /// Upscaling is not supported, so the original size will be returned. + /// + public override Image DecodeSpecialized(JpegDecoderOptions options, Stream stream, CancellationToken cancellationToken) { - Guard.NotNull(stream, nameof(stream)); - - using var decoder = new JpegDecoderCore(configuration, this); - return decoder.Decode(configuration, stream, cancellationToken); + using JpegDecoderCore decoder = new(options); + return decoder.Decode(options.GeneralOptions.Configuration, stream, cancellationToken); } - /// - public Image Decode(Configuration configuration, Stream stream, CancellationToken cancellationToken) - => this.Decode(configuration, stream, cancellationToken); - - /// - /// Placeholder summary. - /// - /// Placeholder2 - /// Placeholder3 - /// Placeholder4 - /// Placeholder5 - /// Placeholder6 - internal Image DecodeInto(Configuration configuration, Stream stream, Size targetSize, CancellationToken cancellationToken) - => this.DecodeInto(configuration, stream, targetSize, cancellationToken); - - /// - /// Decodes and downscales the image from the specified stream if possible. - /// - /// The pixel format. - /// Configuration. - /// Stream. - /// Target size. - /// Cancellation token. - internal Image DecodeInto(Configuration configuration, Stream stream, Size targetSize, CancellationToken cancellationToken) - where TPixel : unmanaged, IPixel - { - Guard.NotNull(stream, nameof(stream)); - - using var decoder = new JpegDecoderCore(configuration, this); - using var bufferedReadStream = new BufferedReadStream(configuration, stream); - try - { - return decoder.DecodeInto(bufferedReadStream, targetSize, cancellationToken); - } - catch (InvalidMemoryOperationException ex) - { - throw new InvalidImageContentException(((IImageDecoderInternals)decoder).Dimensions, ex); - } - } + /// + /// + /// Unlike , when + /// is passed, the codec may not be able to scale efficiently to + /// the exact scale factor requested, so returns a size that approximates that scale. + /// Upscaling is not supported, so the original size will be returned. + /// + public override Image DecodeSpecialized(JpegDecoderOptions options, Stream stream, CancellationToken cancellationToken) + => this.DecodeSpecialized(options, stream, cancellationToken); /// - public IImageInfo Identify(Configuration configuration, Stream stream, CancellationToken cancellationToken) + public override IImageInfo IdentifySpecialized(JpegDecoderOptions options, Stream stream, CancellationToken cancellationToken) { Guard.NotNull(stream, nameof(stream)); - using var decoder = new JpegDecoderCore(configuration, this); - return decoder.Identify(configuration, stream, cancellationToken); + using JpegDecoderCore decoder = new(options); + return decoder.Identify(options.GeneralOptions.Configuration, stream, cancellationToken); } } } diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs index d5997e412..4be75f2a1 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs @@ -28,7 +28,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// Originally ported from /// with additional fixes for both performance and common encoding errors. /// - internal sealed class JpegDecoderCore : IRawJpegData, IImageDecoderInternals + internal sealed class JpegDecoderCore : IRawJpegData, IImageDecoderInternals { /// /// The only supported precision @@ -116,31 +116,36 @@ namespace SixLabors.ImageSharp.Formats.Jpeg private int? resetInterval; /// - /// Initializes a new instance of the class. + /// The global configuration. /// - /// The configuration. - /// The options. - public JpegDecoderCore(Configuration configuration, IJpegDecoderOptions options) - { - this.Configuration = configuration ?? Configuration.Default; - this.IgnoreMetadata = options.IgnoreMetadata; - } + private readonly Configuration configuration; - /// - public Configuration Configuration { get; } + /// + /// Whether to skip metadata during decode. + /// + private readonly bool skipMetadata; /// - /// Gets the frame + /// Initializes a new instance of the class. /// - public JpegFrame Frame { get; private set; } + /// The decoder options. + public JpegDecoderCore(JpegDecoderOptions options) + { + this.Options = options; + this.configuration = options.GeneralOptions.Configuration; + this.skipMetadata = options.GeneralOptions.SkipMetadata; + } + + /// + public JpegDecoderOptions Options { get; } /// - Size IImageDecoderInternals.Dimensions => this.Frame.PixelSize; + public Size Dimensions => this.Frame.PixelSize; /// - /// Gets a value indicating whether the metadata should be ignored when the image is being decoded. + /// Gets the frame /// - public bool IgnoreMetadata { get; } + public JpegFrame Frame { get; private set; } /// /// Gets the decoded by this decoder instance. @@ -201,48 +206,33 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// public Image Decode(BufferedReadStream stream, CancellationToken cancellationToken) where TPixel : unmanaged, IPixel - => this.Decode(stream, targetSize: null, cancellationToken); - - /// - public IImageInfo Identify(BufferedReadStream stream, CancellationToken cancellationToken) { - this.ParseStream(stream, spectralConverter: null, cancellationToken); + using var spectralConverter = new SpectralConverter(this.configuration, this.Options.GeneralOptions.TargetSize); + this.ParseStream(stream, spectralConverter, cancellationToken); this.InitExifProfile(); this.InitIccProfile(); this.InitIptcProfile(); this.InitXmpProfile(); this.InitDerivedMetadataProperties(); - Size pixelSize = this.Frame.PixelSize; - return new ImageInfo(new PixelTypeInfo(this.Frame.BitsPerPixel), pixelSize.Width, pixelSize.Height, this.Metadata); + return new Image( + this.configuration, + spectralConverter.GetPixelBuffer(cancellationToken), + this.Metadata); } - /// - /// Decodes and downscales the image from the specified stream if possible. - /// - /// The pixel format. - /// Stream. - /// Target size. - /// Cancellation token. - internal Image DecodeInto(BufferedReadStream stream, Size targetSize, CancellationToken cancellationToken) - where TPixel : unmanaged, IPixel - => this.Decode(stream, targetSize, cancellationToken); - - private Image Decode(BufferedReadStream stream, Size? targetSize, CancellationToken cancellationToken) - where TPixel : unmanaged, IPixel + /// + public IImageInfo Identify(BufferedReadStream stream, CancellationToken cancellationToken) { - using var spectralConverter = new SpectralConverter(this.Configuration, targetSize); - this.ParseStream(stream, spectralConverter, cancellationToken); + this.ParseStream(stream, spectralConverter: null, cancellationToken); this.InitExifProfile(); this.InitIccProfile(); this.InitIptcProfile(); this.InitXmpProfile(); this.InitDerivedMetadataProperties(); - return new Image( - this.Configuration, - spectralConverter.GetPixelBuffer(cancellationToken), - this.Metadata); + Size pixelSize = this.Frame.PixelSize; + return new ImageInfo(new PixelTypeInfo(this.Frame.BitsPerPixel), pixelSize.Width, pixelSize.Height, this.Metadata); } /// @@ -262,7 +252,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg } using var ms = new MemoryStream(tableBytes); - using var stream = new BufferedReadStream(this.Configuration, ms); + using var stream = new BufferedReadStream(this.configuration, ms); // Check for the Start Of Image marker. int bytesRead = stream.Read(this.markerBuffer, 0, 2); @@ -809,7 +799,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg { const int ExifMarkerLength = 6; const int XmpMarkerLength = 29; - if (remaining < ExifMarkerLength || this.IgnoreMetadata) + if (remaining < ExifMarkerLength || this.skipMetadata) { // Skip the application header length. stream.Skip(remaining); @@ -847,7 +837,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg if (ProfileResolver.IsProfile(this.temp, ProfileResolver.XmpMarker.Slice(0, ExifMarkerLength))) { const int remainingXmpMarkerBytes = XmpMarkerLength - ExifMarkerLength; - if (remaining < remainingXmpMarkerBytes || this.IgnoreMetadata) + if (remaining < remainingXmpMarkerBytes || this.skipMetadata) { // Skip the application header length. stream.Skip(remaining); @@ -889,7 +879,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg { // Length is 14 though we only need to check 12. const int Icclength = 14; - if (remaining < Icclength || this.IgnoreMetadata) + if (remaining < Icclength || this.skipMetadata) { stream.Skip(remaining); return; @@ -930,7 +920,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// The remaining bytes in the segment block. private void ProcessApp13Marker(BufferedReadStream stream, int remaining) { - if (remaining < ProfileResolver.AdobePhotoshopApp13Marker.Length || this.IgnoreMetadata) + if (remaining < ProfileResolver.AdobePhotoshopApp13Marker.Length || this.skipMetadata) { stream.Skip(remaining); return; @@ -1310,8 +1300,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg } IJpegComponent component = decodingComponentType is ComponentType.Huffman ? - new JpegComponent(this.Configuration.MemoryAllocator, this.Frame, componentId, h, v, quantTableIndex, i) : - new ArithmeticDecodingComponent(this.Configuration.MemoryAllocator, this.Frame, componentId, h, v, quantTableIndex, i); + new JpegComponent(this.configuration.MemoryAllocator, this.Frame, componentId, h, v, quantTableIndex, i) : + new ArithmeticDecodingComponent(this.configuration.MemoryAllocator, this.Frame, componentId, h, v, quantTableIndex, i); this.Frame.Components[i] = (JpegComponent)component; this.Frame.ComponentIds[i] = componentId; @@ -1348,7 +1338,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg } int length = remaining; - using (IMemoryOwner buffer = this.Configuration.MemoryAllocator.Allocate(totalBufferSize)) + using (IMemoryOwner buffer = this.configuration.MemoryAllocator.Allocate(totalBufferSize)) { Span bufferSpan = buffer.GetSpan(); Span huffmanLengthsSpan = bufferSpan.Slice(0, codeLengthsByteSize); diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoderOptions.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoderOptions.cs new file mode 100644 index 000000000..80e680cd0 --- /dev/null +++ b/src/ImageSharp/Formats/Jpeg/JpegDecoderOptions.cs @@ -0,0 +1,14 @@ +// Copyright (c) Six Labors. +// Licensed under the Six Labors Split License. + +namespace SixLabors.ImageSharp.Formats.Jpeg +{ + /// + /// Configuration options for decoding Jpeg images. + /// + public sealed class JpegDecoderOptions : ISpecializedDecoderOptions + { + /// + public DecoderOptions GeneralOptions { get; set; } = new(); + } +} diff --git a/src/ImageSharp/Formats/Pbm/PbmDecoderOptions.cs b/src/ImageSharp/Formats/Pbm/PbmDecoderOptions.cs index c0b885650..1253d72b3 100644 --- a/src/ImageSharp/Formats/Pbm/PbmDecoderOptions.cs +++ b/src/ImageSharp/Formats/Pbm/PbmDecoderOptions.cs @@ -1,5 +1,5 @@ // Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. +// Licensed under the Six Labors Split License. namespace SixLabors.ImageSharp.Formats.Pbm { diff --git a/src/ImageSharp/Formats/Png/PngDecoderOptions.cs b/src/ImageSharp/Formats/Png/PngDecoderOptions.cs index 9619bbe7f..722d80325 100644 --- a/src/ImageSharp/Formats/Png/PngDecoderOptions.cs +++ b/src/ImageSharp/Formats/Png/PngDecoderOptions.cs @@ -1,5 +1,5 @@ // Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. +// Licensed under the Six Labors Split License. namespace SixLabors.ImageSharp.Formats.Png { diff --git a/src/ImageSharp/Formats/Tga/TgaDecoderOptions.cs b/src/ImageSharp/Formats/Tga/TgaDecoderOptions.cs index 7483618c4..89ec90430 100644 --- a/src/ImageSharp/Formats/Tga/TgaDecoderOptions.cs +++ b/src/ImageSharp/Formats/Tga/TgaDecoderOptions.cs @@ -1,5 +1,5 @@ // Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. +// Licensed under the Six Labors Split License. namespace SixLabors.ImageSharp.Formats.Tga { diff --git a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/JpegTiffCompression.cs b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/JpegTiffCompression.cs index d0543917a..50698d64d 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/JpegTiffCompression.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/JpegTiffCompression.cs @@ -18,7 +18,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors /// internal sealed class JpegTiffCompression : TiffBaseDecompressor { - private readonly Configuration configuration; + private readonly JpegDecoderOptions options; private readonly byte[] jpegTables; @@ -27,14 +27,14 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors /// /// Initializes a new instance of the class. /// - /// The configuration. + /// The specialized jpeg decoder options. /// The memoryAllocator to use for buffer allocations. /// The image width. /// The bits per pixel. /// The JPEG tables containing the quantization and/or Huffman tables. /// The photometric interpretation. public JpegTiffCompression( - Configuration configuration, + JpegDecoderOptions options, MemoryAllocator memoryAllocator, int width, int bitsPerPixel, @@ -42,7 +42,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors TiffPhotometricInterpretation photometricInterpretation) : base(memoryAllocator, width, bitsPerPixel) { - this.configuration = configuration; + this.options = options; this.jpegTables = jpegTables; this.photometricInterpretation = photometricInterpretation; } @@ -52,14 +52,14 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors { if (this.jpegTables != null) { - using var jpegDecoder = new JpegDecoderCore(this.configuration, new JpegDecoder()); - + using var jpegDecoder = new JpegDecoderCore(this.options); + Configuration configuration = this.options.GeneralOptions.Configuration; switch (this.photometricInterpretation) { case TiffPhotometricInterpretation.BlackIsZero: case TiffPhotometricInterpretation.WhiteIsZero: { - using SpectralConverter spectralConverterGray = new GrayJpegSpectralConverter(this.configuration); + using SpectralConverter spectralConverterGray = new GrayJpegSpectralConverter(configuration); var scanDecoderGray = new HuffmanScanDecoder(stream, spectralConverterGray, CancellationToken.None); jpegDecoder.LoadTables(this.jpegTables, scanDecoderGray); jpegDecoder.ParseStream(stream, spectralConverterGray, CancellationToken.None); @@ -73,8 +73,10 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors case TiffPhotometricInterpretation.YCbCr: case TiffPhotometricInterpretation.Rgb: { - using SpectralConverter spectralConverter = this.photometricInterpretation == TiffPhotometricInterpretation.YCbCr ? - new RgbJpegSpectralConverter(this.configuration) : new SpectralConverter(this.configuration); + using SpectralConverter spectralConverter = this.photometricInterpretation == TiffPhotometricInterpretation.YCbCr + ? new RgbJpegSpectralConverter(this.options.GeneralOptions.Configuration) + : new SpectralConverter(this.options.GeneralOptions.Configuration); + var scanDecoder = new HuffmanScanDecoder(stream, spectralConverter, CancellationToken.None); jpegDecoder.LoadTables(this.jpegTables, scanDecoder); jpegDecoder.ParseStream(stream, spectralConverter, CancellationToken.None); diff --git a/src/ImageSharp/Formats/Tiff/Compression/TiffDecompressorsFactory.cs b/src/ImageSharp/Formats/Tiff/Compression/TiffDecompressorsFactory.cs index 5d6793660..086db4b0a 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/TiffDecompressorsFactory.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/TiffDecompressorsFactory.cs @@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression internal static class TiffDecompressorsFactory { public static TiffBaseDecompressor Create( - Configuration configuration, + DecoderOptions options, TiffDecoderCompressionType method, MemoryAllocator allocator, TiffPhotometricInterpretation photometricInterpretation, @@ -58,7 +58,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression case TiffDecoderCompressionType.Jpeg: DebugGuard.IsTrue(predictor == TiffPredictor.None, "Predictor should only be used with lzw or deflate compression"); - return new JpegTiffCompression(configuration, allocator, width, bitsPerPixel, jpegTables, photometricInterpretation); + return new JpegTiffCompression(new() { GeneralOptions = options }, allocator, width, bitsPerPixel, jpegTables, photometricInterpretation); default: throw TiffThrowHelper.NotSupportedDecompressor(nameof(method)); diff --git a/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs b/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs index 06a950e73..cec199736 100644 --- a/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs +++ b/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs @@ -373,7 +373,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff } using TiffBaseDecompressor decompressor = TiffDecompressorsFactory.Create( - this.configuration, + this.Options.GeneralOptions, this.CompressionType, this.memoryAllocator, this.PhotometricInterpretation, @@ -453,7 +453,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff Buffer2D pixels = frame.PixelBuffer; using TiffBaseDecompressor decompressor = TiffDecompressorsFactory.Create( - this.configuration, + this.Options.GeneralOptions, this.CompressionType, this.memoryAllocator, this.PhotometricInterpretation, diff --git a/src/ImageSharp/Formats/Tiff/TiffDecoderOptions.cs b/src/ImageSharp/Formats/Tiff/TiffDecoderOptions.cs index ec3b43797..b22cf001e 100644 --- a/src/ImageSharp/Formats/Tiff/TiffDecoderOptions.cs +++ b/src/ImageSharp/Formats/Tiff/TiffDecoderOptions.cs @@ -1,5 +1,5 @@ // Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. +// Licensed under the Six Labors Split License. namespace SixLabors.ImageSharp.Formats.Tiff { diff --git a/src/ImageSharp/Formats/Webp/WebpDecoderOptions.cs b/src/ImageSharp/Formats/Webp/WebpDecoderOptions.cs index e574b0c72..8e8218472 100644 --- a/src/ImageSharp/Formats/Webp/WebpDecoderOptions.cs +++ b/src/ImageSharp/Formats/Webp/WebpDecoderOptions.cs @@ -1,5 +1,5 @@ // Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. +// Licensed under the Six Labors Split License. namespace SixLabors.ImageSharp.Formats.Webp { diff --git a/src/ImageSharp/Image.Decode.cs b/src/ImageSharp/Image.Decode.cs index 3fcd44d3a..efa337d6d 100644 --- a/src/ImageSharp/Image.Decode.cs +++ b/src/ImageSharp/Image.Decode.cs @@ -44,14 +44,14 @@ namespace SixLabors.ImageSharp /// /// By reading the header on the provided stream this calculates the images format. /// + /// The general configuration. /// The image stream to read the header from. - /// The configuration. /// The mime type or null if none found. - private static IImageFormat InternalDetectFormat(Stream stream, Configuration config) + private static IImageFormat InternalDetectFormat(Configuration configuration, Stream stream) { // We take a minimum of the stream length vs the max header size and always check below // to ensure that only formats that headers fit within the given buffer length are tested. - int headerSize = (int)Math.Min(config.MaxHeaderSize, stream.Length); + int headerSize = (int)Math.Min(configuration.MaxHeaderSize, stream.Length); if (headerSize <= 0) { return null; @@ -80,7 +80,7 @@ namespace SixLabors.ImageSharp // and does that data match the format specification? // Individual formats should still check since they are public. IImageFormat format = null; - foreach (IImageFormatDetector formatDetector in config.ImageFormatsManager.FormatDetectors) + foreach (IImageFormatDetector formatDetector in configuration.ImageFormatsManager.FormatDetectors) { if (formatDetector.HeaderSize <= headerSize) { @@ -98,73 +98,73 @@ namespace SixLabors.ImageSharp /// /// By reading the header on the provided stream this calculates the images format. /// + /// The general decoder options. /// The image stream to read the header from. - /// The configuration. /// The IImageFormat. /// The image format or null if none found. - private static IImageDecoder DiscoverDecoder(Stream stream, Configuration config, out IImageFormat format) + private static IImageDecoder DiscoverDecoder(DecoderOptions options, Stream stream, out IImageFormat format) { - format = InternalDetectFormat(stream, config); + format = InternalDetectFormat(options.Configuration, stream); return format != null - ? config.ImageFormatsManager.FindDecoder(format) + ? options.Configuration.ImageFormatsManager.FindDecoder(format) : null; } /// /// Decodes the image stream to the current image. /// + /// The general decoder options. /// The stream. - /// the configuration. /// The token to monitor for cancellation requests. /// The pixel format. /// /// A new . /// - private static (Image Image, IImageFormat Format) Decode(Stream stream, Configuration config, CancellationToken cancellationToken = default) + private static (Image Image, IImageFormat Format) Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken = default) where TPixel : unmanaged, IPixel { - IImageDecoder decoder = DiscoverDecoder(stream, config, out IImageFormat format); + IImageDecoder decoder = DiscoverDecoder(options, stream, out IImageFormat format); if (decoder is null) { return (null, null); } - Image img = decoder.Decode(config, stream, cancellationToken); + Image img = decoder.Decode(options, stream, cancellationToken); return (img, format); } - private static (Image Image, IImageFormat Format) Decode(Stream stream, Configuration config, CancellationToken cancellationToken = default) + private static (Image Image, IImageFormat Format) Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken = default) { - IImageDecoder decoder = DiscoverDecoder(stream, config, out IImageFormat format); + IImageDecoder decoder = DiscoverDecoder(options, stream, out IImageFormat format); if (decoder is null) { return (null, null); } - Image img = decoder.Decode(config, stream, cancellationToken); + Image img = decoder.Decode(options, stream, cancellationToken); return (img, format); } /// /// Reads the raw image information from the specified stream. /// + /// The general decoder options. /// The stream. - /// the configuration. /// The token to monitor for cancellation requests. /// /// The or null if a suitable info detector is not found. /// - private static (IImageInfo ImageInfo, IImageFormat Format) InternalIdentity(Stream stream, Configuration config, CancellationToken cancellationToken = default) + private static (IImageInfo ImageInfo, IImageFormat Format) InternalIdentity(DecoderOptions options, Stream stream, CancellationToken cancellationToken = default) { - IImageDecoder decoder = DiscoverDecoder(stream, config, out IImageFormat format); + IImageDecoder decoder = DiscoverDecoder(options, stream, out IImageFormat format); if (decoder is not IImageInfoDetector detector) { return (null, null); } - IImageInfo info = detector?.Identify(config, stream, cancellationToken); + IImageInfo info = detector?.Identify(options, stream, cancellationToken); return (info, format); } } diff --git a/src/ImageSharp/Image.FromBytes.cs b/src/ImageSharp/Image.FromBytes.cs index 342143bb5..0d7fb27f4 100644 --- a/src/ImageSharp/Image.FromBytes.cs +++ b/src/ImageSharp/Image.FromBytes.cs @@ -9,232 +9,30 @@ using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp { /// - /// Adds static methods allowing the creation of new image from a byte array. + /// Adds static methods allowing the creation of new image from a byte span. /// public abstract partial class Image { - /// - /// By reading the header on the provided byte array this calculates the images format. - /// - /// The byte array containing encoded image data to read the header from. - /// The data is null. - /// The format or null if none found. - public static IImageFormat DetectFormat(byte[] data) - => DetectFormat(Configuration.Default, data); - - /// - /// By reading the header on the provided byte array this calculates the images format. - /// - /// The configuration. - /// The byte array containing encoded image data to read the header from. - /// The configuration is null. - /// The data is null. - /// The mime type or null if none found. - public static IImageFormat DetectFormat(Configuration configuration, byte[] data) - { - Guard.NotNull(data, nameof(data)); - - using (var stream = new MemoryStream(data, 0, data.Length, false, true)) - { - return DetectFormat(configuration, stream); - } - } - - /// - /// Reads the raw image information from the specified stream without fully decoding it. - /// - /// The byte array containing encoded image data to read the header from. - /// The data is null. - /// The data is not readable. - /// - /// The or null if suitable info detector not found. - /// - public static IImageInfo Identify(byte[] data) => Identify(data, out IImageFormat _); - - /// - /// Reads the raw image information from the specified stream without fully decoding it. - /// - /// The byte array containing encoded image data to read the header from. - /// The format type of the decoded image. - /// The data is null. - /// The data is not readable. - /// - /// The or null if suitable info detector not found. - /// - public static IImageInfo Identify(byte[] data, out IImageFormat format) => Identify(Configuration.Default, data, out format); - - /// - /// Reads the raw image information from the specified stream without fully decoding it. - /// - /// The configuration. - /// The byte array containing encoded image data to read the header from. - /// The format type of the decoded image. - /// The configuration is null. - /// The data is null. - /// The data is not readable. - /// - /// The or null if suitable info detector is not found. - /// - public static IImageInfo Identify(Configuration configuration, byte[] data, out IImageFormat format) - { - Guard.NotNull(data, nameof(data)); - - using (var stream = new MemoryStream(data, 0, data.Length, false, true)) - { - return Identify(configuration, stream, out format); - } - } - - /// - /// Load a new instance of from the given encoded byte array. - /// - /// The byte array containing image data. - /// The configuration is null. - /// The data is null. - /// A new . - public static Image Load(byte[] data) - => Load(Configuration.Default, data); - - /// - /// Load a new instance of from the given encoded byte array. - /// - /// The byte array containing encoded image data. - /// The pixel format. - /// The data is null. - /// Image format not recognised. - /// Image format is not supported. - /// Image contains invalid content. - /// A new . - public static Image Load(byte[] data) - where TPixel : unmanaged, IPixel - => Load(Configuration.Default, data); - - /// - /// Load a new instance of from the given encoded byte array. - /// - /// The byte array containing image data. - /// The mime type of the decoded image. - /// The pixel format. - /// The data is null. - /// Image format not recognised. - /// Image format is not supported. - /// Image contains invalid content. - /// A new . - public static Image Load(byte[] data, out IImageFormat format) - where TPixel : unmanaged, IPixel - => Load(Configuration.Default, data, out format); - - /// - /// Load a new instance of from the given encoded byte array. - /// - /// The configuration options. - /// The byte array containing encoded image data. - /// The pixel format. - /// The configuration is null. - /// The data is null. - /// Image format not recognised. - /// Image format is not supported. - /// Image contains invalid content. - /// A new . - public static Image Load(Configuration configuration, byte[] data) - where TPixel : unmanaged, IPixel - { - Guard.NotNull(data, nameof(data)); - - using (var stream = new MemoryStream(data, 0, data.Length, false, true)) - { - return Load(configuration, stream); - } - } - - /// - /// Load a new instance of from the given encoded byte array. - /// - /// The configuration options. - /// The byte array containing encoded image data. - /// The of the decoded image. - /// The pixel format. - /// The configuration is null. - /// The data is null. - /// Image format not recognised. - /// Image format is not supported. - /// Image contains invalid content. - /// A new . - public static Image Load(Configuration configuration, byte[] data, out IImageFormat format) - where TPixel : unmanaged, IPixel - { - Guard.NotNull(data, nameof(data)); - - using (var stream = new MemoryStream(data, 0, data.Length, false, true)) - { - return Load(configuration, stream, out format); - } - } - - /// - /// Load a new instance of from the given encoded byte array. - /// - /// The byte array containing encoded image data. - /// The decoder. - /// The pixel format. - /// The data is null. - /// Image format not recognised. - /// Image format is not supported. - /// Image contains invalid content. - /// A new . - public static Image Load(byte[] data, IImageDecoder decoder) - where TPixel : unmanaged, IPixel - { - Guard.NotNull(data, nameof(data)); - - using (var stream = new MemoryStream(data, 0, data.Length, false, true)) - { - return Load(stream, decoder); - } - } - - /// - /// Load a new instance of from the given encoded byte array. - /// - /// The Configuration. - /// The byte array containing encoded image data. - /// The decoder. - /// The pixel format. - /// The configuration is null. - /// The data is null. - /// Image format not recognised. - /// Image format is not supported. - /// Image contains invalid content. - /// A new . - public static Image Load(Configuration configuration, byte[] data, IImageDecoder decoder) - where TPixel : unmanaged, IPixel - { - Guard.NotNull(data, nameof(data)); - - using (var stream = new MemoryStream(data, 0, data.Length, false, true)) - { - return Load(configuration, stream, decoder); - } - } - /// /// By reading the header on the provided byte span this calculates the images format. /// /// The byte span containing encoded image data to read the header from. /// The format or null if none found. - public static IImageFormat DetectFormat(ReadOnlySpan data) => DetectFormat(Configuration.Default, data); + public static IImageFormat DetectFormat(ReadOnlySpan data) + => DetectFormat(DecoderOptions.Default, data); /// /// By reading the header on the provided byte span this calculates the images format. /// - /// The configuration. + /// The general decoder options. /// The byte span containing encoded image data to read the header from. - /// The configuration is null. + /// The options are null. /// The mime type or null if none found. - public static IImageFormat DetectFormat(Configuration configuration, ReadOnlySpan data) + public static IImageFormat DetectFormat(DecoderOptions options, ReadOnlySpan data) { - Guard.NotNull(configuration, nameof(configuration)); + Guard.NotNull(options, nameof(options.Configuration)); + Configuration configuration = options.Configuration; int maxHeaderSize = configuration.MaxHeaderSize; if (maxHeaderSize <= 0) { @@ -265,7 +63,7 @@ namespace SixLabors.ImageSharp /// A new . public static Image Load(ReadOnlySpan data) where TPixel : unmanaged, IPixel - => Load(Configuration.Default, data); + => Load(DecoderOptions.Default, data); /// /// Load a new instance of from the given encoded byte span. @@ -279,177 +77,51 @@ namespace SixLabors.ImageSharp /// A new . public static Image Load(ReadOnlySpan data, out IImageFormat format) where TPixel : unmanaged, IPixel - => Load(Configuration.Default, data, out format); + => Load(DecoderOptions.Default, data, out format); /// /// Load a new instance of from the given encoded byte span. /// + /// The general decoder options. /// The byte span containing encoded image data. - /// The decoder. /// The pixel format. + /// The options are null. /// Image format not recognised. /// Image contains invalid content. /// Image format is not supported. /// A new . - public static Image Load(ReadOnlySpan data, IImageDecoder decoder) - where TPixel : unmanaged, IPixel - => Load(Configuration.Default, data, decoder); - - /// - /// Load a new instance of from the given encoded byte span. - /// - /// The configuration options. - /// The byte span containing encoded image data. - /// The pixel format. - /// The configuration is null. - /// Image format not recognised. - /// Image contains invalid content. - /// Image format is not supported. - /// A new . - public static unsafe Image Load(Configuration configuration, ReadOnlySpan data) - where TPixel : unmanaged, IPixel - { - fixed (byte* ptr = &data.GetPinnableReference()) - { - using (var stream = new UnmanagedMemoryStream(ptr, data.Length)) - { - return Load(configuration, stream); - } - } - } - - /// - /// Load a new instance of from the given encoded byte span. - /// - /// The Configuration. - /// The byte span containing image data. - /// The decoder. - /// The pixel format. - /// The configuration is null. - /// Image format not recognised. - /// Image contains invalid content. - /// Image format is not supported. - /// A new . - public static unsafe Image Load( - Configuration configuration, - ReadOnlySpan data, - IImageDecoder decoder) + public static unsafe Image Load(DecoderOptions options, ReadOnlySpan data) where TPixel : unmanaged, IPixel { fixed (byte* ptr = &data.GetPinnableReference()) { - using (var stream = new UnmanagedMemoryStream(ptr, data.Length)) - { - return Load(configuration, stream, decoder); - } + using var stream = new UnmanagedMemoryStream(ptr, data.Length); + return Load(options, stream); } } /// /// Load a new instance of from the given encoded byte span. /// - /// The configuration options. + /// The general decoder options. /// The byte span containing image data. /// The of the decoded image. /// The pixel format. - /// The configuration is null. + /// The options are null. /// Image format not recognised. /// Image contains invalid content. /// Image format is not supported. /// A new . public static unsafe Image Load( - Configuration configuration, + DecoderOptions options, ReadOnlySpan data, out IImageFormat format) where TPixel : unmanaged, IPixel { fixed (byte* ptr = &data.GetPinnableReference()) { - using (var stream = new UnmanagedMemoryStream(ptr, data.Length)) - { - return Load(configuration, stream, out format); - } - } - } - - /// - /// Load a new instance of from the given encoded byte array. - /// - /// The byte array containing image data. - /// The detected format. - /// The configuration is null. - /// The data is null. - /// Image format not recognised. - /// Image contains invalid content. - /// Image format is not supported. - /// The . - public static Image Load(byte[] data, out IImageFormat format) - => Load(Configuration.Default, data, out format); - - /// - /// Load a new instance of from the given encoded byte array. - /// - /// The byte array containing encoded image data. - /// The decoder. - /// The data is null. - /// Image format not recognised. - /// Image contains invalid content. - /// Image format is not supported. - /// The . - public static Image Load(byte[] data, IImageDecoder decoder) - => Load(Configuration.Default, data, decoder); - - /// - /// Load a new instance of from the given encoded byte array. - /// - /// The configuration for the decoder. - /// The byte array containing encoded image data. - /// The configuration is null. - /// The data is null. - /// Image format not recognised. - /// Image contains invalid content. - /// Image format is not supported. - /// The . - public static Image Load(Configuration configuration, byte[] data) - => Load(configuration, data, out _); - - /// - /// Load a new instance of from the given encoded byte array. - /// - /// The configuration for the decoder. - /// The byte array containing image data. - /// The decoder. - /// The configuration is null. - /// The data is null. - /// Image format not recognised. - /// Image contains invalid content. - /// Image format is not supported. - /// The . - public static Image Load(Configuration configuration, byte[] data, IImageDecoder decoder) - { - using (var stream = new MemoryStream(data, 0, data.Length, false, true)) - { - return Load(configuration, stream, decoder); - } - } - - /// - /// Load a new instance of from the given encoded byte array. - /// - /// The configuration for the decoder. - /// The byte array containing image data. - /// The mime type of the decoded image. - /// The configuration is null. - /// The data is null. - /// Image format not recognised. - /// Image contains invalid content. - /// Image format is not supported. - /// The . - public static Image Load(Configuration configuration, byte[] data, out IImageFormat format) - { - using (var stream = new MemoryStream(data, 0, data.Length, false, true)) - { - return Load(configuration, stream, out format); + using var stream = new UnmanagedMemoryStream(ptr, data.Length); + return Load(options, stream, out format); } } @@ -462,21 +134,7 @@ namespace SixLabors.ImageSharp /// Image format is not supported. /// The . public static Image Load(ReadOnlySpan data) - => Load(Configuration.Default, data); - - /// - /// Load a new instance of from the given encoded byte span. - /// - /// The byte span containing image data. - /// The decoder. - /// The data is null. - /// The decoder is null. - /// Image format not recognised. - /// Image contains invalid content. - /// Image format is not supported. - /// The . - public static Image Load(ReadOnlySpan data, IImageDecoder decoder) - => Load(Configuration.Default, data, decoder); + => Load(DecoderOptions.Default, data); /// /// Load a new instance of from the given encoded byte array. @@ -489,65 +147,37 @@ namespace SixLabors.ImageSharp /// Image format is not supported. /// The . public static Image Load(ReadOnlySpan data, out IImageFormat format) - => Load(Configuration.Default, data, out format); + => Load(DecoderOptions.Default, data, out format); /// /// Decodes a new instance of from the given encoded byte span. /// - /// The configuration options. + /// The general decoder options. /// The byte span containing image data. /// The . - public static Image Load(Configuration configuration, ReadOnlySpan data) - => Load(configuration, data, out _); + public static Image Load(DecoderOptions options, ReadOnlySpan data) + => Load(options, data, out _); /// /// Load a new instance of from the given encoded byte span. /// - /// The Configuration. - /// The byte span containing image data. - /// The decoder. - /// The configuration is null. - /// The decoder is null. - /// The stream is not readable or the image format is not supported. - /// Image format not recognised. - /// Image contains invalid content. - /// The . - public static unsafe Image Load( - Configuration configuration, - ReadOnlySpan data, - IImageDecoder decoder) - { - fixed (byte* ptr = &data.GetPinnableReference()) - { - using (var stream = new UnmanagedMemoryStream(ptr, data.Length)) - { - return Load(configuration, stream, decoder); - } - } - } - - /// - /// Load a new instance of from the given encoded byte span. - /// - /// The configuration options. + /// The general decoder options. /// The byte span containing image data. /// The of the decoded image.> - /// The configuration is null. + /// The options are null. /// Image format not recognised. /// Image contains invalid content. /// Image format is not supported. /// The . public static unsafe Image Load( - Configuration configuration, + DecoderOptions options, ReadOnlySpan data, out IImageFormat format) { fixed (byte* ptr = &data.GetPinnableReference()) { - using (var stream = new UnmanagedMemoryStream(ptr, data.Length)) - { - return Load(configuration, stream, out format); - } + using var stream = new UnmanagedMemoryStream(ptr, data.Length); + return Load(options, stream, out format); } } } diff --git a/src/ImageSharp/Image.FromFile.cs b/src/ImageSharp/Image.FromFile.cs index 79c036d24..6594ed218 100644 --- a/src/ImageSharp/Image.FromFile.cs +++ b/src/ImageSharp/Image.FromFile.cs @@ -21,23 +21,21 @@ namespace SixLabors.ImageSharp /// The image file to open and to read the header from. /// The mime type or null if none found. public static IImageFormat DetectFormat(string filePath) - => DetectFormat(Configuration.Default, filePath); + => DetectFormat(DecoderOptions.Default, filePath); /// /// By reading the header on the provided file this calculates the images mime type. /// - /// The configuration. + /// The general decoder options. /// The image file to open and to read the header from. /// The configuration is null. /// The mime type or null if none found. - public static IImageFormat DetectFormat(Configuration configuration, string filePath) + public static IImageFormat DetectFormat(DecoderOptions options, string filePath) { - Guard.NotNull(configuration, nameof(configuration)); + Guard.NotNull(options, nameof(options)); - using (Stream file = configuration.FileSystem.OpenRead(filePath)) - { - return DetectFormat(configuration, file); - } + using Stream file = options.Configuration.FileSystem.OpenRead(filePath); + return DetectFormat(options, file); } /// @@ -59,25 +57,23 @@ namespace SixLabors.ImageSharp /// The or null if suitable info detector not found. /// public static IImageInfo Identify(string filePath, out IImageFormat format) - => Identify(Configuration.Default, filePath, out format); + => Identify(DecoderOptions.Default, filePath, out format); /// /// Reads the raw image information from the specified stream without fully decoding it. /// - /// The configuration. + /// The general decoder options. /// The image file to open and to read the header from. /// The format type of the decoded image. /// The configuration is null. /// /// The or null if suitable info detector is not found. /// - public static IImageInfo Identify(Configuration configuration, string filePath, out IImageFormat format) + public static IImageInfo Identify(DecoderOptions options, string filePath, out IImageFormat format) { - Guard.NotNull(configuration, nameof(configuration)); - using (Stream file = configuration.FileSystem.OpenRead(filePath)) - { - return Identify(configuration, file, out format); - } + Guard.NotNull(options, nameof(options)); + using Stream file = options.Configuration.FileSystem.OpenRead(filePath); + return Identify(options, file, out format); } /// @@ -91,12 +87,12 @@ namespace SixLabors.ImageSharp /// property set to null if suitable info detector is not found. /// public static Task IdentifyAsync(string filePath, CancellationToken cancellationToken = default) - => IdentifyAsync(Configuration.Default, filePath, cancellationToken); + => IdentifyAsync(DecoderOptions.Default, filePath, cancellationToken); /// /// Reads the raw image information from the specified stream without fully decoding it. /// - /// The configuration. + /// The general decoder options. /// The image file to open and to read the header from. /// The token to monitor for cancellation requests. /// The configuration is null. @@ -105,12 +101,12 @@ namespace SixLabors.ImageSharp /// property set to null if suitable info detector is not found. /// public static async Task IdentifyAsync( - Configuration configuration, + DecoderOptions options, string filePath, CancellationToken cancellationToken = default) { - (IImageInfo ImageInfo, IImageFormat Format) res = await IdentifyWithFormatAsync(configuration, filePath, cancellationToken) - .ConfigureAwait(false); + (IImageInfo ImageInfo, IImageFormat Format) res = + await IdentifyWithFormatAsync(options, filePath, cancellationToken).ConfigureAwait(false); return res.ImageInfo; } @@ -127,12 +123,12 @@ namespace SixLabors.ImageSharp public static Task<(IImageInfo ImageInfo, IImageFormat Format)> IdentifyWithFormatAsync( string filePath, CancellationToken cancellationToken = default) - => IdentifyWithFormatAsync(Configuration.Default, filePath, cancellationToken); + => IdentifyWithFormatAsync(DecoderOptions.Default, filePath, cancellationToken); /// /// Reads the raw image information from the specified stream without fully decoding it. /// - /// The configuration. + /// The general decoder options. /// The image file to open and to read the header from. /// The token to monitor for cancellation requests. /// The configuration is null. @@ -141,13 +137,13 @@ namespace SixLabors.ImageSharp /// property set to null if suitable info detector is not found. /// public static async Task<(IImageInfo ImageInfo, IImageFormat Format)> IdentifyWithFormatAsync( - Configuration configuration, + DecoderOptions options, string filePath, CancellationToken cancellationToken = default) { - Guard.NotNull(configuration, nameof(configuration)); - using Stream stream = configuration.FileSystem.OpenRead(filePath); - return await IdentifyWithFormatAsync(configuration, stream, cancellationToken) + Guard.NotNull(options, nameof(options)); + using Stream stream = options.Configuration.FileSystem.OpenRead(filePath); + return await IdentifyWithFormatAsync(options, stream, cancellationToken) .ConfigureAwait(false); } @@ -160,7 +156,7 @@ namespace SixLabors.ImageSharp /// /// The . public static Image Load(string path) - => Load(Configuration.Default, path); + => Load(DecoderOptions.Default, path); /// /// Create a new instance of the class from the given file. @@ -172,12 +168,12 @@ namespace SixLabors.ImageSharp /// /// A new . public static Image Load(string path, out IImageFormat format) - => Load(Configuration.Default, path, out format); + => Load(DecoderOptions.Default, path, out format); /// /// Create a new instance of the class from the given file. /// - /// The configuration for the decoder. + /// The general decoder options. /// The file path to the image. /// The configuration is null. /// The path is null. @@ -185,13 +181,13 @@ namespace SixLabors.ImageSharp /// Image format is not supported. /// Image contains invalid content. /// The . - public static Image Load(Configuration configuration, string path) - => Load(configuration, path, out _); + public static Image Load(DecoderOptions options, string path) + => Load(options, path, out _); /// /// Create a new instance of the class from the given file. /// - /// The configuration for the decoder. + /// The general decoder options. /// The file path to the image. /// The token to monitor for cancellation requests. /// The configuration is null. @@ -201,40 +197,16 @@ namespace SixLabors.ImageSharp /// Image contains invalid content. /// A representing the asynchronous operation. public static async Task LoadAsync( - Configuration configuration, + DecoderOptions options, string path, CancellationToken cancellationToken = default) { - using Stream stream = configuration.FileSystem.OpenRead(path); - (Image img, _) = await LoadWithFormatAsync(configuration, stream, cancellationToken) + using Stream stream = options.Configuration.FileSystem.OpenRead(path); + (Image img, _) = await LoadWithFormatAsync(options, stream, cancellationToken) .ConfigureAwait(false); return img; } - /// - /// Create a new instance of the class from the given file. - /// - /// The Configuration. - /// The file path to the image. - /// The decoder. - /// The configuration is null. - /// The path is null. - /// The decoder is null. - /// Image format not recognised. - /// Image format is not supported. - /// Image contains invalid content. - /// The . - public static Image Load(Configuration configuration, string path, IImageDecoder decoder) - { - Guard.NotNull(configuration, nameof(configuration)); - Guard.NotNull(path, nameof(path)); - - using (Stream stream = configuration.FileSystem.OpenRead(path)) - { - return Load(configuration, stream, decoder); - } - } - /// /// Create a new instance of the class from the given file. /// @@ -248,99 +220,7 @@ namespace SixLabors.ImageSharp /// Image contains invalid content. /// A representing the asynchronous operation. public static Task LoadAsync(string path, CancellationToken cancellationToken = default) - => LoadAsync(Configuration.Default, path, cancellationToken); - - /// - /// Create a new instance of the class from the given file. - /// - /// The file path to the image. - /// The decoder. - /// The token to monitor for cancellation requests. - /// The configuration is null. - /// The path is null. - /// The decoder is null. - /// Image format not recognised. - /// Image format is not supported. - /// Image contains invalid content. - /// A representing the asynchronous operation. - public static Task LoadAsync(string path, IImageDecoder decoder, CancellationToken cancellationToken = default) - => LoadAsync(Configuration.Default, path, decoder, cancellationToken); - - /// - /// Create a new instance of the class from the given file. - /// - /// The file path to the image. - /// The decoder. - /// The token to monitor for cancellation requests. - /// The configuration is null. - /// The path is null. - /// The decoder is null. - /// Image format not recognised. - /// Image format is not supported. - /// Image contains invalid content. - /// The pixel format. - /// A representing the asynchronous operation. - public static Task> LoadAsync(string path, IImageDecoder decoder, CancellationToken cancellationToken = default) - where TPixel : unmanaged, IPixel - => LoadAsync(Configuration.Default, path, decoder, cancellationToken); - - /// - /// Create a new instance of the class from the given file. - /// - /// The Configuration. - /// The file path to the image. - /// The decoder. - /// The token to monitor for cancellation requests. - /// The configuration is null. - /// The path is null. - /// The decoder is null. - /// Image format not recognised. - /// Image format is not supported. - /// Image contains invalid content. - /// A representing the asynchronous operation. - public static async Task LoadAsync( - Configuration configuration, - string path, - IImageDecoder decoder, - CancellationToken cancellationToken = default) - { - Guard.NotNull(configuration, nameof(configuration)); - Guard.NotNull(path, nameof(path)); - - using Stream stream = configuration.FileSystem.OpenRead(path); - return await LoadAsync(configuration, stream, decoder, cancellationToken) - .ConfigureAwait(false); - } - - /// - /// Create a new instance of the class from the given file. - /// - /// The Configuration. - /// The file path to the image. - /// The decoder. - /// The token to monitor for cancellation requests. - /// The configuration is null. - /// The path is null. - /// The decoder is null. - /// Image format not recognised. - /// Image format is not supported. - /// Image contains invalid content. - /// The pixel format. - /// A representing the asynchronous operation. - public static async Task> LoadAsync( - Configuration configuration, - string path, - IImageDecoder decoder, - CancellationToken cancellationToken = default) - where TPixel : unmanaged, IPixel - { - Guard.NotNull(configuration, nameof(configuration)); - Guard.NotNull(path, nameof(path)); - - using Stream stream = configuration.FileSystem.OpenRead(path); - return await LoadAsync(configuration, stream, decoder, cancellationToken) - .ConfigureAwait(false); - } + => LoadAsync(DecoderOptions.Default, path, cancellationToken); /// /// Create a new instance of the class from the given file. @@ -356,12 +236,12 @@ namespace SixLabors.ImageSharp /// A representing the asynchronous operation. public static Task> LoadAsync(string path, CancellationToken cancellationToken = default) where TPixel : unmanaged, IPixel - => LoadAsync(Configuration.Default, path, cancellationToken); + => LoadAsync(DecoderOptions.Default, path, cancellationToken); /// /// Create a new instance of the class from the given file. /// - /// The configuration for the decoder. + /// The general decoder options. /// The file path to the image. /// The token to monitor for cancellation requests. /// The configuration is null. @@ -372,31 +252,19 @@ namespace SixLabors.ImageSharp /// The pixel format. /// A representing the asynchronous operation. public static async Task> LoadAsync( - Configuration configuration, + DecoderOptions options, string path, CancellationToken cancellationToken = default) where TPixel : unmanaged, IPixel { - using Stream stream = configuration.FileSystem.OpenRead(path); - (Image img, _) = await LoadWithFormatAsync(configuration, stream, cancellationToken) - .ConfigureAwait(false); + Guard.NotNull(options, nameof(options)); + + using Stream stream = options.Configuration.FileSystem.OpenRead(path); + (Image img, _) = + await LoadWithFormatAsync(options, stream, cancellationToken).ConfigureAwait(false); return img; } - /// - /// Create a new instance of the class from the given file. - /// - /// The file path to the image. - /// The decoder. - /// The path is null. - /// The decoder is null. - /// Image format not recognised. - /// Image format is not supported. - /// Image contains invalid content. - /// The . - public static Image Load(string path, IImageDecoder decoder) - => Load(Configuration.Default, path, decoder); - /// /// Create a new instance of the class from the given file. /// @@ -409,7 +277,7 @@ namespace SixLabors.ImageSharp /// A new . public static Image Load(string path) where TPixel : unmanaged, IPixel - => Load(Configuration.Default, path); + => Load(DecoderOptions.Default, path); /// /// Create a new instance of the class from the given file. @@ -424,12 +292,12 @@ namespace SixLabors.ImageSharp /// A new . public static Image Load(string path, out IImageFormat format) where TPixel : unmanaged, IPixel - => Load(Configuration.Default, path, out format); + => Load(DecoderOptions.Default, path, out format); /// /// Create a new instance of the class from the given file. /// - /// The configuration options. + /// The general decoder options. /// The file path to the image. /// The configuration is null. /// The path is null. @@ -438,22 +306,20 @@ namespace SixLabors.ImageSharp /// Image contains invalid content. /// The pixel format. /// A new . - public static Image Load(Configuration configuration, string path) + public static Image Load(DecoderOptions options, string path) where TPixel : unmanaged, IPixel { - Guard.NotNull(configuration, nameof(configuration)); + Guard.NotNull(options, nameof(options)); Guard.NotNull(path, nameof(path)); - using (Stream stream = configuration.FileSystem.OpenRead(path)) - { - return Load(configuration, stream); - } + using Stream stream = options.Configuration.FileSystem.OpenRead(path); + return Load(options, stream); } /// /// Create a new instance of the class from the given file. /// - /// The configuration options. + /// The general decoder options. /// The file path to the image. /// The mime type of the decoded image. /// The configuration is null. @@ -463,23 +329,21 @@ namespace SixLabors.ImageSharp /// Image contains invalid content. /// The pixel format. /// A new . - public static Image Load(Configuration configuration, string path, out IImageFormat format) + public static Image Load(DecoderOptions options, string path, out IImageFormat format) where TPixel : unmanaged, IPixel { - Guard.NotNull(configuration, nameof(configuration)); + Guard.NotNull(options, nameof(options)); Guard.NotNull(path, nameof(path)); - using (Stream stream = configuration.FileSystem.OpenRead(path)) - { - return Load(configuration, stream, out format); - } + using Stream stream = options.Configuration.FileSystem.OpenRead(path); + return Load(options, stream, out format); } /// /// Create a new instance of the class from the given file. /// The pixel type is selected by the decoder. /// - /// The configuration options. + /// The general decoder options. /// The file path to the image. /// The mime type of the decoded image. /// The configuration is null. @@ -488,56 +352,13 @@ namespace SixLabors.ImageSharp /// Image format is not supported. /// Image contains invalid content. /// A new . - public static Image Load(Configuration configuration, string path, out IImageFormat format) - { - Guard.NotNull(configuration, nameof(configuration)); - Guard.NotNull(path, nameof(path)); - - using (Stream stream = configuration.FileSystem.OpenRead(path)) - { - return Load(configuration, stream, out format); - } - } - - /// - /// Create a new instance of the class from the given file. - /// - /// The file path to the image. - /// The decoder. - /// The path is null. - /// Image format not recognised. - /// Image format is not supported. - /// Image contains invalid content. - /// The pixel format. - /// A new . - public static Image Load(string path, IImageDecoder decoder) - where TPixel : unmanaged, IPixel - => Load(Configuration.Default, path, decoder); - - /// - /// Create a new instance of the class from the given file. - /// - /// The Configuration. - /// The file path to the image. - /// The decoder. - /// The configuration is null. - /// The path is null. - /// The decoder is null. - /// Image format not recognised. - /// Image format is not supported. - /// Image contains invalid content. - /// The pixel format. - /// A new . - public static Image Load(Configuration configuration, string path, IImageDecoder decoder) - where TPixel : unmanaged, IPixel + public static Image Load(DecoderOptions options, string path, out IImageFormat format) { - Guard.NotNull(configuration, nameof(configuration)); + Guard.NotNull(options, nameof(options)); Guard.NotNull(path, nameof(path)); - using (Stream stream = configuration.FileSystem.OpenRead(path)) - { - return Load(configuration, stream, decoder); - } + using Stream stream = options.Configuration.FileSystem.OpenRead(path); + return Load(options, stream, out format); } } } diff --git a/src/ImageSharp/Image.FromStream.cs b/src/ImageSharp/Image.FromStream.cs index 803d8a754..86baa1c1a 100644 --- a/src/ImageSharp/Image.FromStream.cs +++ b/src/ImageSharp/Image.FromStream.cs @@ -26,19 +26,19 @@ namespace SixLabors.ImageSharp /// The stream is not readable. /// The format type or null if none found. public static IImageFormat DetectFormat(Stream stream) - => DetectFormat(Configuration.Default, stream); + => DetectFormat(DecoderOptions.Default, stream); /// /// By reading the header on the provided stream this calculates the images format type. /// - /// The configuration. + /// The general decoder options. /// The image stream to read the header from. - /// The configuration is null. + /// The options are null. /// The stream is null. /// The stream is not readable. /// The format type or null if none found. - public static IImageFormat DetectFormat(Configuration configuration, Stream stream) - => WithSeekableStream(configuration, stream, s => InternalDetectFormat(s, configuration)); + public static IImageFormat DetectFormat(DecoderOptions options, Stream stream) + => WithSeekableStream(options, stream, s => InternalDetectFormat(options.Configuration, s)); /// /// By reading the header on the provided stream this calculates the images format type. @@ -49,23 +49,23 @@ namespace SixLabors.ImageSharp /// The stream is not readable. /// A representing the asynchronous operation or null if none is found. public static Task DetectFormatAsync(Stream stream, CancellationToken cancellationToken = default) - => DetectFormatAsync(Configuration.Default, stream, cancellationToken); + => DetectFormatAsync(DecoderOptions.Default, stream, cancellationToken); /// /// By reading the header on the provided stream this calculates the images format type. /// - /// The configuration. + /// The general decoder options. /// The image stream to read the header from. /// The token to monitor for cancellation requests. - /// The configuration is null. + /// The options are null. /// The stream is null. /// The stream is not readable. /// A representing the asynchronous operation. - public static Task DetectFormatAsync(Configuration configuration, Stream stream, CancellationToken cancellationToken = default) + public static Task DetectFormatAsync(DecoderOptions options, Stream stream, CancellationToken cancellationToken = default) => WithSeekableStreamAsync( - configuration, + options, stream, - (s, _) => InternalDetectFormat(s, configuration), + (s, _) => InternalDetectFormat(options.Configuration, s), cancellationToken); /// @@ -94,7 +94,7 @@ namespace SixLabors.ImageSharp /// a suitable detector is not found. /// public static Task IdentifyAsync(Stream stream, CancellationToken cancellationToken = default) - => IdentifyAsync(Configuration.Default, stream, cancellationToken); + => IdentifyAsync(DecoderOptions.Default, stream, cancellationToken); /// /// Reads the raw image information from the specified stream without fully decoding it. @@ -108,30 +108,30 @@ namespace SixLabors.ImageSharp /// The or null if a suitable info detector is not found. /// public static IImageInfo Identify(Stream stream, out IImageFormat format) - => Identify(Configuration.Default, stream, out format); + => Identify(DecoderOptions.Default, stream, out format); /// /// Reads the raw image information from the specified stream without fully decoding it. /// - /// The configuration. + /// The general decoder options. /// The image stream to read the information from. - /// The configuration is null. + /// The options are null. /// The stream is null. /// The stream is not readable. /// Image contains invalid content. /// /// The or null if a suitable info detector is not found. /// - public static IImageInfo Identify(Configuration configuration, Stream stream) - => Identify(configuration, stream, out _); + public static IImageInfo Identify(DecoderOptions options, Stream stream) + => Identify(options, stream, out _); /// /// Reads the raw image information from the specified stream without fully decoding it. /// - /// The configuration. + /// The general decoder options. /// The image stream to read the information from. /// The token to monitor for cancellation requests. - /// The configuration is null. + /// The options are null. /// The stream is null. /// The stream is not readable. /// Image contains invalid content. @@ -140,30 +140,30 @@ namespace SixLabors.ImageSharp /// a suitable detector is not found. /// public static async Task IdentifyAsync( - Configuration configuration, + DecoderOptions options, Stream stream, CancellationToken cancellationToken = default) { - (IImageInfo ImageInfo, IImageFormat Format) res = await IdentifyWithFormatAsync(configuration, stream, cancellationToken).ConfigureAwait(false); + (IImageInfo ImageInfo, IImageFormat Format) res = await IdentifyWithFormatAsync(options, stream, cancellationToken).ConfigureAwait(false); return res.ImageInfo; } /// /// Reads the raw image information from the specified stream without fully decoding it. /// - /// The configuration. + /// The general decoder options. /// The image stream to read the information from. /// The format type of the decoded image. - /// The configuration is null. + /// The options are null. /// The stream is null. /// The stream is not readable. /// Image contains invalid content. /// /// The or null if a suitable info detector is not found. /// - public static IImageInfo Identify(Configuration configuration, Stream stream, out IImageFormat format) + public static IImageInfo Identify(DecoderOptions options, Stream stream, out IImageFormat format) { - (IImageInfo ImageInfo, IImageFormat Format) data = WithSeekableStream(configuration, stream, s => InternalIdentity(s, configuration ?? Configuration.Default)); + (IImageInfo ImageInfo, IImageFormat Format) data = WithSeekableStream(options, stream, s => InternalIdentity(options, s)); format = data.Format; return data.ImageInfo; @@ -174,7 +174,7 @@ namespace SixLabors.ImageSharp /// /// The image stream to read the information from. /// The token to monitor for cancellation requests. - /// The configuration is null. + /// The options are null. /// The stream is null. /// The stream is not readable. /// Image contains invalid content. @@ -185,15 +185,15 @@ namespace SixLabors.ImageSharp public static Task<(IImageInfo ImageInfo, IImageFormat Format)> IdentifyWithFormatAsync( Stream stream, CancellationToken cancellationToken = default) - => IdentifyWithFormatAsync(Configuration.Default, stream, cancellationToken); + => IdentifyWithFormatAsync(DecoderOptions.Default, stream, cancellationToken); /// /// Reads the raw image information from the specified stream without fully decoding it. /// - /// The configuration. + /// The general decoder options. /// The image stream to read the information from. /// The token to monitor for cancellation requests. - /// The configuration is null. + /// The options are null. /// The stream is null. /// The stream is not readable. /// Image contains invalid content. @@ -202,13 +202,13 @@ namespace SixLabors.ImageSharp /// property set to null if suitable info detector is not found. /// public static Task<(IImageInfo ImageInfo, IImageFormat Format)> IdentifyWithFormatAsync( - Configuration configuration, + DecoderOptions options, Stream stream, CancellationToken cancellationToken = default) => WithSeekableStreamAsync( - configuration, + options, stream, - (s, ct) => InternalIdentity(s, configuration ?? Configuration.Default, ct), + (s, ct) => InternalIdentity(options, s, ct), cancellationToken); /// @@ -223,7 +223,7 @@ namespace SixLabors.ImageSharp /// Image contains invalid content. /// The . public static Image Load(Stream stream, out IImageFormat format) - => Load(Configuration.Default, stream, out format); + => Load(DecoderOptions.Default, stream, out format); /// /// Decode a new instance of the class from the given stream. @@ -237,7 +237,7 @@ namespace SixLabors.ImageSharp /// Image contains invalid content. /// A representing the asynchronous operation. public static Task<(Image Image, IImageFormat Format)> LoadWithFormatAsync(Stream stream, CancellationToken cancellationToken = default) - => LoadWithFormatAsync(Configuration.Default, stream, cancellationToken); + => LoadWithFormatAsync(DecoderOptions.Default, stream, cancellationToken); /// /// Decode a new instance of the class from the given stream. @@ -249,7 +249,7 @@ namespace SixLabors.ImageSharp /// Image format not recognised. /// Image contains invalid content. /// The . - public static Image Load(Stream stream) => Load(Configuration.Default, stream); + public static Image Load(Stream stream) => Load(DecoderOptions.Default, stream); /// /// Decode a new instance of the class from the given stream. @@ -263,116 +263,37 @@ namespace SixLabors.ImageSharp /// Image contains invalid content. /// A representing the asynchronous operation. public static Task LoadAsync(Stream stream, CancellationToken cancellationToken = default) - => LoadAsync(Configuration.Default, stream, cancellationToken); + => LoadAsync(DecoderOptions.Default, stream, cancellationToken); /// /// Decode a new instance of the class from the given stream. - /// The pixel format is selected by the decoder. /// + /// The general decoder options. /// The stream containing image information. - /// The decoder. + /// The options are null. /// The stream is null. - /// The decoder is null. - /// The stream is not readable or the image format is not supported. - /// Image format not recognised. - /// Image contains invalid content. - /// The . - public static Image Load(Stream stream, IImageDecoder decoder) - => Load(Configuration.Default, stream, decoder); - - /// - /// Decode a new instance of the class from the given stream. - /// The pixel format is selected by the decoder. - /// - /// The stream containing image information. - /// The decoder. - /// The token to monitor for cancellation requests. - /// The stream is null. - /// The decoder is null. - /// The stream is not readable or the image format is not supported. - /// Image format not recognised. - /// Image contains invalid content. - /// A representing the asynchronous operation. - public static Task LoadAsync(Stream stream, IImageDecoder decoder, CancellationToken cancellationToken = default) - => LoadAsync(Configuration.Default, stream, decoder, cancellationToken); - - /// - /// Decode a new instance of the class from the given stream. - /// The pixel format is selected by the decoder. - /// - /// The configuration for the decoder. - /// The stream containing image information. - /// The decoder. - /// The configuration is null. - /// The stream is null. - /// The decoder is null. /// The stream is not readable or the image format is not supported. /// Image format not recognised. /// Image contains invalid content. /// A new . - public static Image Load(Configuration configuration, Stream stream, IImageDecoder decoder) - { - Guard.NotNull(decoder, nameof(decoder)); - return WithSeekableStream(configuration, stream, s => decoder.Decode(configuration, s, default)); - } + public static Image Load(DecoderOptions options, Stream stream) + => Load(options, stream, out _); /// /// Decode a new instance of the class from the given stream. - /// The pixel format is selected by the decoder. /// - /// The configuration for the decoder. + /// The general decoder options. /// The stream containing image information. - /// The decoder. /// The token to monitor for cancellation requests. - /// The configuration is null. + /// The options are null. /// The stream is null. - /// The decoder is null. /// The stream is not readable or the image format is not supported. /// Image format not recognised. /// Image contains invalid content. /// A representing the asynchronous operation. - public static Task LoadAsync( - Configuration configuration, - Stream stream, - IImageDecoder decoder, - CancellationToken cancellationToken = default) + public static async Task LoadAsync(DecoderOptions options, Stream stream, CancellationToken cancellationToken = default) { - Guard.NotNull(decoder, nameof(decoder)); - return WithSeekableStreamAsync( - configuration, - stream, - (s, ct) => decoder.Decode(configuration, s, ct), - cancellationToken); - } - - /// - /// Decode a new instance of the class from the given stream. - /// - /// The configuration for the decoder. - /// The stream containing image information. - /// The configuration is null. - /// The stream is null. - /// The stream is not readable or the image format is not supported. - /// Image format not recognised. - /// Image contains invalid content. - /// A new . - public static Image Load(Configuration configuration, Stream stream) => Load(configuration, stream, out _); - - /// - /// Decode a new instance of the class from the given stream. - /// - /// The configuration for the decoder. - /// The stream containing image information. - /// The token to monitor for cancellation requests. - /// The configuration is null. - /// The stream is null. - /// The stream is not readable or the image format is not supported. - /// Image format not recognised. - /// Image contains invalid content. - /// A representing the asynchronous operation. - public static async Task LoadAsync(Configuration configuration, Stream stream, CancellationToken cancellationToken = default) - { - (Image Image, IImageFormat Format) fmt = await LoadWithFormatAsync(configuration, stream, cancellationToken) + (Image Image, IImageFormat Format) fmt = await LoadWithFormatAsync(options, stream, cancellationToken) .ConfigureAwait(false); return fmt.Image; } @@ -389,7 +310,7 @@ namespace SixLabors.ImageSharp /// A new . public static Image Load(Stream stream) where TPixel : unmanaged, IPixel - => Load(Configuration.Default, stream); + => Load(DecoderOptions.Default, stream); /// /// Create a new instance of the class from the given stream. @@ -404,7 +325,7 @@ namespace SixLabors.ImageSharp /// A representing the asynchronous operation. public static Task> LoadAsync(Stream stream, CancellationToken cancellationToken = default) where TPixel : unmanaged, IPixel - => LoadAsync(Configuration.Default, stream, cancellationToken); + => LoadAsync(DecoderOptions.Default, stream, cancellationToken); /// /// Create a new instance of the class from the given stream. @@ -419,7 +340,7 @@ namespace SixLabors.ImageSharp /// A new . public static Image Load(Stream stream, out IImageFormat format) where TPixel : unmanaged, IPixel - => Load(Configuration.Default, stream, out format); + => Load(DecoderOptions.Default, stream, out format); /// /// Create a new instance of the class from the given stream. @@ -434,119 +355,41 @@ namespace SixLabors.ImageSharp /// A representing the asynchronous operation. public static Task<(Image Image, IImageFormat Format)> LoadWithFormatAsync(Stream stream, CancellationToken cancellationToken = default) where TPixel : unmanaged, IPixel - => LoadWithFormatAsync(Configuration.Default, stream, cancellationToken); + => LoadWithFormatAsync(DecoderOptions.Default, stream, cancellationToken); /// /// Create a new instance of the class from the given stream. /// + /// The general decoder options. /// The stream containing image information. - /// The decoder. + /// The options are null. /// The stream is null. /// The stream is not readable or the image format is not supported. /// Image format not recognised. /// Image contains invalid content. /// The pixel format. /// A new . - public static Image Load(Stream stream, IImageDecoder decoder) + public static Image Load(DecoderOptions options, Stream stream) where TPixel : unmanaged, IPixel - => WithSeekableStream(Configuration.Default, stream, s => decoder.Decode(Configuration.Default, s, default)); + => Load(options, stream, out IImageFormat _); /// /// Create a new instance of the class from the given stream. /// - /// The stream containing image information. - /// The decoder. - /// The token to monitor for cancellation requests. - /// The stream is null. - /// The stream is not readable or the image format is not supported. - /// Image format not recognised. - /// Image contains invalid content. - /// The pixel format. - /// A representing the asynchronous operation. - public static Task> LoadAsync(Stream stream, IImageDecoder decoder, CancellationToken cancellationToken = default) - where TPixel : unmanaged, IPixel - => WithSeekableStreamAsync( - Configuration.Default, - stream, - (s, ct) => decoder.Decode(Configuration.Default, s, ct), - cancellationToken); - - /// - /// Create a new instance of the class from the given stream. - /// - /// The Configuration. - /// The stream containing image information. - /// The decoder. - /// The configuration is null. - /// The stream is null. - /// The stream is not readable or the image format is not supported. - /// Image format not recognised. - /// Image contains invalid content. - /// The pixel format. - /// A new . - public static Image Load(Configuration configuration, Stream stream, IImageDecoder decoder) - where TPixel : unmanaged, IPixel - => WithSeekableStream(configuration, stream, s => decoder.Decode(configuration, s, default)); - - /// - /// Create a new instance of the class from the given stream. - /// - /// The Configuration. - /// The stream containing image information. - /// The decoder. - /// The token to monitor for cancellation requests. - /// The configuration is null. - /// The stream is null. - /// The stream is not readable or the image format is not supported. - /// Image format not recognised. - /// Image contains invalid content. - /// The pixel format. - /// A representing the asynchronous operation. - public static Task> LoadAsync( - Configuration configuration, - Stream stream, - IImageDecoder decoder, - CancellationToken cancellationToken = default) - where TPixel : unmanaged, IPixel - => WithSeekableStreamAsync( - configuration, - stream, - (s, ct) => decoder.Decode(configuration, s, ct), - cancellationToken); - - /// - /// Create a new instance of the class from the given stream. - /// - /// The configuration options. - /// The stream containing image information. - /// The configuration is null. - /// The stream is null. - /// The stream is not readable or the image format is not supported. - /// Image format not recognised. - /// Image contains invalid content. - /// The pixel format. - /// A new . - public static Image Load(Configuration configuration, Stream stream) - where TPixel : unmanaged, IPixel - => Load(configuration, stream, out IImageFormat _); - - /// - /// Create a new instance of the class from the given stream. - /// - /// The configuration options. + /// The general decoder options. /// The stream containing image information. /// The format type of the decoded image. - /// The configuration is null. + /// The options are null. /// The stream is null. /// The stream is not readable or the image format is not supported. /// Image format not recognised. /// Image contains invalid content. /// The pixel format. /// A representing the asynchronous operation. - public static Image Load(Configuration configuration, Stream stream, out IImageFormat format) + public static Image Load(DecoderOptions options, Stream stream, out IImageFormat format) where TPixel : unmanaged, IPixel { - (Image Image, IImageFormat Format) data = WithSeekableStream(configuration, stream, s => Decode(s, configuration)); + (Image Image, IImageFormat Format) data = WithSeekableStream(options, stream, s => Decode(options, s)); format = data.Format; @@ -558,7 +401,7 @@ namespace SixLabors.ImageSharp var sb = new StringBuilder(); sb.AppendLine("Image cannot be loaded. Available decoders:"); - foreach (KeyValuePair val in configuration.ImageFormatsManager.ImageDecoders) + foreach (KeyValuePair val in options.Configuration.ImageFormatsManager.ImageDecoders) { sb.AppendFormat(" - {0} : {1}{2}", val.Key.Name, val.Value.GetType().Name, Environment.NewLine); } @@ -569,24 +412,24 @@ namespace SixLabors.ImageSharp /// /// Create a new instance of the class from the given stream. /// - /// The configuration options. + /// The general decoder options. /// The stream containing image information. /// The token to monitor for cancellation requests. - /// The configuration is null. + /// The options are null. /// The stream is null. /// The stream is not readable or the image format is not supported. /// Image format not recognised. /// Image contains invalid content. /// A representing the asynchronous operation. public static async Task<(Image Image, IImageFormat Format)> LoadWithFormatAsync( - Configuration configuration, + DecoderOptions options, Stream stream, CancellationToken cancellationToken = default) { (Image Image, IImageFormat Format) data = await WithSeekableStreamAsync( - configuration, + options, stream, - (s, ct) => Decode(s, configuration, ct), + (s, ct) => Decode(options, s, ct), cancellationToken) .ConfigureAwait(false); @@ -598,7 +441,7 @@ namespace SixLabors.ImageSharp var sb = new StringBuilder(); sb.AppendLine("Image cannot be loaded. Available decoders:"); - foreach (KeyValuePair val in configuration.ImageFormatsManager.ImageDecoders) + foreach (KeyValuePair val in options.Configuration.ImageFormatsManager.ImageDecoders) { sb.AppendFormat(" - {0} : {1}{2}", val.Key.Name, val.Value.GetType().Name, Environment.NewLine); } @@ -609,10 +452,10 @@ namespace SixLabors.ImageSharp /// /// Create a new instance of the class from the given stream. /// - /// The configuration options. + /// The general decoder options. /// The stream containing image information. /// The token to monitor for cancellation requests. - /// The configuration is null. + /// The options are null. /// The stream is null. /// The stream is not readable or the image format is not supported. /// Image format not recognised. @@ -620,16 +463,16 @@ namespace SixLabors.ImageSharp /// The pixel format. /// A representing the asynchronous operation. public static async Task<(Image Image, IImageFormat Format)> LoadWithFormatAsync( - Configuration configuration, + DecoderOptions options, Stream stream, CancellationToken cancellationToken = default) where TPixel : unmanaged, IPixel { (Image Image, IImageFormat Format) data = await WithSeekableStreamAsync( - configuration, + options, stream, - (s, ct) => Decode(s, configuration, ct), + (s, ct) => Decode(options, s, ct), cancellationToken) .ConfigureAwait(false); @@ -641,7 +484,7 @@ namespace SixLabors.ImageSharp var sb = new StringBuilder(); sb.AppendLine("Image cannot be loaded. Available decoders:"); - foreach (KeyValuePair val in configuration.ImageFormatsManager.ImageDecoders) + foreach (KeyValuePair val in options.Configuration.ImageFormatsManager.ImageDecoders) { sb.AppendFormat(" - {0} : {1}{2}", val.Key.Name, val.Value.GetType().Name, Environment.NewLine); } @@ -652,10 +495,10 @@ namespace SixLabors.ImageSharp /// /// Create a new instance of the class from the given stream. /// - /// The configuration options. + /// The general decoder options. /// The stream containing image information. /// The token to monitor for cancellation requests. - /// The configuration is null. + /// The options are null. /// The stream is null. /// The stream is not readable or the image format is not supported. /// Image format not recognised. @@ -663,12 +506,12 @@ namespace SixLabors.ImageSharp /// The pixel format. /// A representing the asynchronous operation. public static async Task> LoadAsync( - Configuration configuration, + DecoderOptions options, Stream stream, CancellationToken cancellationToken = default) where TPixel : unmanaged, IPixel { - (Image img, _) = await LoadWithFormatAsync(configuration, stream, cancellationToken) + (Image img, _) = await LoadWithFormatAsync(options, stream, cancellationToken) .ConfigureAwait(false); return img; } @@ -677,30 +520,30 @@ namespace SixLabors.ImageSharp /// Decode a new instance of the class from the given stream. /// The pixel format is selected by the decoder. /// - /// The configuration options. + /// The general decoder options. /// The stream containing image information. /// The format type of the decoded image. - /// The configuration is null. + /// The options are null. /// The stream is null. /// The stream is not readable or the image format is not supported. /// Image format not recognised. /// Image contains invalid content. /// A new . - public static Image Load(Configuration configuration, Stream stream, out IImageFormat format) + public static Image Load(DecoderOptions options, Stream stream, out IImageFormat format) { - (Image Img, IImageFormat Format) data = WithSeekableStream(configuration, stream, s => Decode(s, configuration)); + (Image img, IImageFormat fmt) = WithSeekableStream(options, stream, s => Decode(options, s)); - format = data.Format; + format = fmt; - if (data.Img != null) + if (img != null) { - return data.Img; + return img; } var sb = new StringBuilder(); sb.AppendLine("Image cannot be loaded. Available decoders:"); - foreach (KeyValuePair val in configuration.ImageFormatsManager.ImageDecoders) + foreach (KeyValuePair val in options.Configuration.ImageFormatsManager.ImageDecoders) { sb.AppendFormat(" - {0} : {1}{2}", val.Key.Name, val.Value.GetType().Name, Environment.NewLine); } @@ -712,16 +555,16 @@ namespace SixLabors.ImageSharp /// Performs the given action against the stream ensuring that it is seekable. /// /// The type of object returned from the action. - /// The configuration. + /// The general decoder options. /// The input stream. /// The action to perform. /// The . private static T WithSeekableStream( - Configuration configuration, + DecoderOptions options, Stream stream, Func action) { - Guard.NotNull(configuration, nameof(configuration)); + Guard.NotNull(options, nameof(options)); Guard.NotNull(stream, nameof(stream)); if (!stream.CanRead) @@ -729,6 +572,7 @@ namespace SixLabors.ImageSharp throw new NotSupportedException("Cannot read from the stream."); } + Configuration configuration = options.Configuration; if (stream.CanSeek) { if (configuration.ReadOrigin == ReadOrigin.Begin) @@ -751,18 +595,18 @@ namespace SixLabors.ImageSharp /// Performs the given action asynchronously against the stream ensuring that it is seekable. /// /// The type of object returned from the action. - /// The configuration. + /// The general decoder options. /// The input stream. /// The action to perform. /// The cancellation token. /// The . private static async Task WithSeekableStreamAsync( - Configuration configuration, + DecoderOptions options, Stream stream, Func action, CancellationToken cancellationToken) { - Guard.NotNull(configuration, nameof(configuration)); + Guard.NotNull(options, nameof(options)); Guard.NotNull(stream, nameof(stream)); if (!stream.CanRead) @@ -770,6 +614,7 @@ namespace SixLabors.ImageSharp throw new NotSupportedException("Cannot read from the stream."); } + Configuration configuration = options.Configuration; if (stream.CanSeek) { if (configuration.ReadOrigin == ReadOrigin.Begin) diff --git a/src/ImageSharp/Image.LoadPixelData.cs b/src/ImageSharp/Image.LoadPixelData.cs index 93563c794..a59f5a34c 100644 --- a/src/ImageSharp/Image.LoadPixelData.cs +++ b/src/ImageSharp/Image.LoadPixelData.cs @@ -16,20 +16,7 @@ namespace SixLabors.ImageSharp /// /// Create a new instance of the class from the raw data. /// - /// The byte array containing image data. - /// The width of the final image. - /// The height of the final image. - /// The pixel format. - /// The data length is incorrect. - /// A new . - public static Image LoadPixelData(TPixel[] data, int width, int height) - where TPixel : unmanaged, IPixel - => LoadPixelData(Configuration.Default, data, width, height); - - /// - /// Create a new instance of the class from the raw data. - /// - /// The byte array containing image data. + /// The readonly span of bytes containing image data. /// The width of the final image. /// The height of the final image. /// The pixel format. @@ -40,22 +27,9 @@ namespace SixLabors.ImageSharp => LoadPixelData(Configuration.Default, data, width, height); /// - /// Create a new instance of the class from the given byte array in format. + /// Create a new instance of the class from the given readonly span of bytes in format. /// - /// The byte array containing image data. - /// The width of the final image. - /// The height of the final image. - /// The pixel format. - /// The data length is incorrect. - /// A new . - public static Image LoadPixelData(byte[] data, int width, int height) - where TPixel : unmanaged, IPixel - => LoadPixelData(Configuration.Default, data, width, height); - - /// - /// Create a new instance of the class from the given byte array in format. - /// - /// The byte array containing image data. + /// The readonly span of bytes containing image data. /// The width of the final image. /// The height of the final image. /// The pixel format. @@ -66,25 +40,10 @@ namespace SixLabors.ImageSharp => LoadPixelData(Configuration.Default, data, width, height); /// - /// Create a new instance of the class from the given byte array in format. - /// - /// The configuration for the decoder. - /// The byte array containing image data. - /// The width of the final image. - /// The height of the final image. - /// The pixel format. - /// The configuration is null. - /// The data length is incorrect. - /// A new . - public static Image LoadPixelData(Configuration configuration, byte[] data, int width, int height) - where TPixel : unmanaged, IPixel - => LoadPixelData(configuration, MemoryMarshal.Cast(new ReadOnlySpan(data)), width, height); - - /// - /// Create a new instance of the class from the given byte array in format. + /// Create a new instance of the class from the given readonly span of bytes in format. /// /// The configuration for the decoder. - /// The byte array containing image data. + /// The readonly span of bytes containing image data. /// The width of the final image. /// The height of the final image. /// The pixel format. @@ -99,22 +58,7 @@ namespace SixLabors.ImageSharp /// Create a new instance of the class from the raw data. /// /// The configuration for the decoder. - /// The Span containing the image Pixel data. - /// The width of the final image. - /// The height of the final image. - /// The pixel format. - /// The configuration is null. - /// The data length is incorrect. - /// A new . - public static Image LoadPixelData(Configuration configuration, TPixel[] data, int width, int height) - where TPixel : unmanaged, IPixel - => LoadPixelData(configuration, new ReadOnlySpan(data), width, height); - - /// - /// Create a new instance of the class from the raw data. - /// - /// The configuration for the decoder. - /// The Span containing the image Pixel data. + /// The readonly span containing the image pixel data. /// The width of the final image. /// The height of the final image. /// The configuration is null. diff --git a/tests/ImageSharp.Benchmarks/LoadResizeSave/LoadResizeSaveStressRunner.cs b/tests/ImageSharp.Benchmarks/LoadResizeSave/LoadResizeSaveStressRunner.cs index c26de9159..bee55600f 100644 --- a/tests/ImageSharp.Benchmarks/LoadResizeSave/LoadResizeSaveStressRunner.cs +++ b/tests/ImageSharp.Benchmarks/LoadResizeSave/LoadResizeSaveStressRunner.cs @@ -13,6 +13,7 @@ using System.Runtime.InteropServices; using System.Threading.Tasks; using ImageMagick; using PhotoSauce.MagicScaler; +using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Formats.Jpeg; using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Tests; @@ -157,7 +158,7 @@ namespace SixLabors.ImageSharp.Benchmarks.LoadResizeSave this.TotalProcessedMegapixels += pixels / 1_000_000.0; } - private string OutputPath(string inputPath, [CallerMemberName]string postfix = null) => + private string OutputPath(string inputPath, [CallerMemberName] string postfix = null) => Path.Combine( this.outputDirectory, Path.GetFileNameWithoutExtension(inputPath) + "-" + postfix + Path.GetExtension(inputPath)); @@ -208,18 +209,15 @@ namespace SixLabors.ImageSharp.Benchmarks.LoadResizeSave using FileStream outputStream = File.Open(this.OutputPath(input), FileMode.Create); // Resize it to fit a 150x150 square - var targetSize = new ImageSharpSize(this.ThumbnailSize, this.ThumbnailSize); + DecoderOptions options = new() + { + TargetSize = new ImageSharpSize(this.ThumbnailSize, this.ThumbnailSize) + }; + var decoder = new JpegDecoder(); - using ImageSharpImage image = decoder.DecodeInto(Configuration.Default, inputStream, targetSize, default); + using ImageSharpImage image = decoder.Decode(options, inputStream, default); this.LogImageProcessed(image.Width, image.Height); - image.Mutate(i => i.Resize(new ResizeOptions - { - Size = targetSize, - Mode = ResizeMode.Max, - Sampler = KnownResamplers.Box - })); - // Reduce the size of the file image.Metadata.ExifProfile = null; image.Metadata.XmpProfile = null; @@ -235,18 +233,19 @@ namespace SixLabors.ImageSharp.Benchmarks.LoadResizeSave using FileStream output = File.Open(this.OutputPath(input), FileMode.Create); // Resize it to fit a 150x150 square. - using ImageSharpImage image = await ImageSharpImage.LoadAsync(input); - this.LogImageProcessed(image.Width, image.Height); - - // Resize checks whether image size and target sizes are equal - image.Mutate(i => i.Resize(new ResizeOptions + DecoderOptions options = new() { - Size = new ImageSharpSize(this.ThumbnailSize, this.ThumbnailSize), - Mode = ResizeMode.Max - })); + TargetSize = new ImageSharpSize(this.ThumbnailSize, this.ThumbnailSize) + }; + + using ImageSharpImage image = await ImageSharpImage.LoadAsync(options, input); + this.LogImageProcessed(image.Width, image.Height); // Reduce the size of the file image.Metadata.ExifProfile = null; + image.Metadata.XmpProfile = null; + image.Metadata.IccProfile = null; + image.Metadata.IptcProfile = null; // Save the results await image.SaveAsync(output, this.imageSharpJpegEncoder);