diff --git a/src/ImageSharp/Configuration.cs b/src/ImageSharp/Configuration.cs index 34bbb61e0..d41e48678 100644 --- a/src/ImageSharp/Configuration.cs +++ b/src/ImageSharp/Configuration.cs @@ -1,272 +1,145 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using SixLabors.ImageSharp.Formats; -using SixLabors.ImageSharp.Formats.Bmp; -using SixLabors.ImageSharp.Formats.Gif; -using SixLabors.ImageSharp.Formats.Jpeg; -using SixLabors.ImageSharp.Formats.Png; -using SixLabors.ImageSharp.IO; -using SixLabors.ImageSharp.Memory; - -namespace SixLabors.ImageSharp -{ - /// - /// Provides initialization code which allows extending the library. - /// - public sealed class Configuration - { - /// - /// A lazily initialized configuration default instance. - /// - private static readonly Lazy Lazy = new Lazy(CreateDefaultInstance); - - /// - /// The list of supported keyed to mime types. - /// - private readonly ConcurrentDictionary mimeTypeEncoders = new ConcurrentDictionary(); - - /// - /// The list of supported keyed to mime types. - /// - private readonly ConcurrentDictionary mimeTypeDecoders = new ConcurrentDictionary(); - - /// - /// The list of supported s. - /// - private readonly ConcurrentBag imageFormats = new ConcurrentBag(); - - /// - /// The list of supported s. - /// - private ConcurrentBag imageFormatDetectors = new ConcurrentBag(); - - /// - /// Initializes a new instance of the class. - /// - public Configuration() - { - } - - /// - /// Initializes a new instance of the class. - /// - /// A collection of configuration modules to register - public Configuration(params IConfigurationModule[] configurationModules) - { - if (configurationModules != null) - { - foreach (IConfigurationModule p in configurationModules) - { - p.Configure(this); - } - } - } - - /// - /// Gets the default instance. - /// - public static Configuration Default { get; } = Lazy.Value; - - /// - /// Gets the global parallel options for processing tasks in parallel. - /// - public ParallelOptions ParallelOptions { get; } = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }; - - /// - /// Gets the currently registered s. - /// - public IEnumerable ImageFormats => this.imageFormats; - - /// - /// Gets or sets the position in a stream to use for reading when using a seekable stream as an image data source. - /// - public ReadOrigin ReadOrigin { get; set; } = ReadOrigin.Current; - - /// - /// Gets or sets the that is currently in use. - /// - public MemoryManager MemoryManager { get; set; } = ArrayPoolMemoryManager.CreateDefault(); - - /// - /// Gets the maximum header size of all the formats. - /// - internal int MaxHeaderSize { get; private set; } - - /// - /// Gets the currently registered s. - /// - internal IEnumerable FormatDetectors => this.imageFormatDetectors; - - /// - /// Gets the currently registered s. - /// - internal IEnumerable> ImageDecoders => this.mimeTypeDecoders; - - /// - /// Gets the currently registered s. - /// - internal IEnumerable> ImageEncoders => this.mimeTypeEncoders; - -#if !NETSTANDARD1_1 - /// - /// Gets or sets the filesystem helper for accessing the local file system. - /// - internal IFileSystem FileSystem { get; set; } = new LocalFileSystem(); -#endif - - /// - /// Gets or sets the image operations provider factory. - /// - internal IImageProcessingContextFactory ImageOperationsProvider { get; set; } = new DefaultImageOperationsProviderFactory(); - - /// - /// Registers a new format provider. - /// - /// The configuration provider to call configure on. - public void Configure(IConfigurationModule configuration) - { - Guard.NotNull(configuration, nameof(configuration)); - configuration.Configure(this); - } - - /// - /// Registers a new format provider. - /// - /// The format to register as a known format. - public void AddImageFormat(IImageFormat format) - { - Guard.NotNull(format, nameof(format)); - Guard.NotNull(format.MimeTypes, nameof(format.MimeTypes)); - Guard.NotNull(format.FileExtensions, nameof(format.FileExtensions)); - this.imageFormats.Add(format); - } - - /// - /// For the specified file extensions type find the e . - /// - /// The extension to discover - /// The if found otherwise null - public IImageFormat FindFormatByFileExtension(string extension) - { - return this.imageFormats.FirstOrDefault(x => x.FileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase)); - } - - /// - /// For the specified mime type find the . - /// - /// The mime-type to discover - /// The if found; otherwise null - public IImageFormat FindFormatByMimeType(string mimeType) - { - return this.imageFormats.FirstOrDefault(x => x.MimeTypes.Contains(mimeType, StringComparer.OrdinalIgnoreCase)); - } - - /// - /// Sets a specific image encoder as the encoder for a specific image format. - /// - /// The image format to register the encoder for. - /// The encoder to use, - public void SetEncoder(IImageFormat imageFormat, IImageEncoder encoder) - { - Guard.NotNull(imageFormat, nameof(imageFormat)); - Guard.NotNull(encoder, nameof(encoder)); - this.AddImageFormat(imageFormat); - this.mimeTypeEncoders.AddOrUpdate(imageFormat, encoder, (s, e) => encoder); - } - - /// - /// Sets a specific image decoder as the decoder for a specific image format. - /// - /// The image format to register the encoder for. - /// The decoder to use, - public void SetDecoder(IImageFormat imageFormat, IImageDecoder decoder) - { - Guard.NotNull(imageFormat, nameof(imageFormat)); - Guard.NotNull(decoder, nameof(decoder)); - this.AddImageFormat(imageFormat); - this.mimeTypeDecoders.AddOrUpdate(imageFormat, decoder, (s, e) => decoder); - } - - /// - /// Removes all the registered image format detectors. - /// - public void ClearImageFormatDetectors() - { - this.imageFormatDetectors = new ConcurrentBag(); - } - - /// - /// Adds a new detector for detecting mime types. - /// - /// The detector to add - public void AddImageFormatDetector(IImageFormatDetector detector) - { - Guard.NotNull(detector, nameof(detector)); - this.imageFormatDetectors.Add(detector); - this.SetMaxHeaderSize(); - } - - /// - /// For the specified mime type find the decoder. - /// - /// The format to discover - /// The if found otherwise null - public IImageDecoder FindDecoder(IImageFormat format) - { - Guard.NotNull(format, nameof(format)); - if (this.mimeTypeDecoders.TryGetValue(format, out IImageDecoder decoder)) - { - return decoder; - } - - return null; - } - - /// - /// For the specified mime type find the encoder. - /// - /// The format to discover - /// The if found otherwise null - public IImageEncoder FindEncoder(IImageFormat format) - { - Guard.NotNull(format, nameof(format)); - if (this.mimeTypeEncoders.TryGetValue(format, out IImageEncoder encoder)) - { - return encoder; - } - - return null; - } - - /// - /// Creates the default instance with the following s preregistered: - /// - /// - /// - /// - /// - /// The default configuration of - internal static Configuration CreateDefaultInstance() - { - return new Configuration( - new PngConfigurationModule(), - new JpegConfigurationModule(), - new GifConfigurationModule(), - new BmpConfigurationModule()); - } - - /// - /// Sets the max header size. - /// - private void SetMaxHeaderSize() - { - this.MaxHeaderSize = this.imageFormatDetectors.Max(x => x.HeaderSize); - } - } -} +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using SixLabors.ImageSharp.Formats; +using SixLabors.ImageSharp.Formats.Bmp; +using SixLabors.ImageSharp.Formats.Gif; +using SixLabors.ImageSharp.Formats.Jpeg; +using SixLabors.ImageSharp.Formats.Png; +using SixLabors.ImageSharp.IO; +using SixLabors.ImageSharp.Memory; + +namespace SixLabors.ImageSharp +{ + /// + /// Provides initialization code which allows extending the library. + /// + public sealed class Configuration + { + /// + /// A lazily initialized configuration default instance. + /// + private static readonly Lazy Lazy = new Lazy(CreateDefaultInstance); + + /// + /// Initializes a new instance of the class. + /// + public Configuration() + { + } + + /// + /// Initializes a new instance of the class. + /// + /// A collection of configuration modules to register + public Configuration(params IConfigurationModule[] configurationModules) + { + if (configurationModules != null) + { + foreach (IConfigurationModule p in configurationModules) + { + p.Configure(this); + } + } + } + + /// + /// Gets the default instance. + /// + public static Configuration Default { get; } = Lazy.Value; + + /// + /// Gets the global parallel options for processing tasks in parallel. + /// + public ParallelOptions ParallelOptions { get; private set; } = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }; + + /// + /// Gets the currently registered s. + /// + public IEnumerable ImageFormats => this.ImageFormatsManager.ImageFormats; + + /// + /// Gets or sets the position in a stream to use for reading when using a seekable stream as an image data source. + /// + public ReadOrigin ReadOrigin { get; set; } = ReadOrigin.Current; + + /// + /// Gets or sets the that is currently in use. + /// + public ImageFormatManager ImageFormatsManager { get; set; } = new ImageFormatManager(); + + /// + /// Gets or sets the that is currently in use. + /// + public MemoryManager MemoryManager { get; set; } = ArrayPoolMemoryManager.CreateDefault(); + + /// + /// Gets the maximum header size of all the formats. + /// + internal int MaxHeaderSize => this.ImageFormatsManager.MaxHeaderSize; + +#if !NETSTANDARD1_1 + /// + /// Gets or sets the filesystem helper for accessing the local file system. + /// + internal IFileSystem FileSystem { get; set; } = new LocalFileSystem(); +#endif + + /// + /// Gets or sets the image operations provider factory. + /// + internal IImageProcessingContextFactory ImageOperationsProvider { get; set; } = new DefaultImageOperationsProviderFactory(); + + /// + /// Registers a new format provider. + /// + /// The configuration provider to call configure on. + public void Configure(IConfigurationModule configuration) + { + Guard.NotNull(configuration, nameof(configuration)); + configuration.Configure(this); + } + + /// + /// Creates a shallow copy of the + /// + /// A new configuration instance + public Configuration ShallowCopy() + { + return new Configuration + { + ParallelOptions = this.ParallelOptions, + ImageFormatsManager = this.ImageFormatsManager, + MemoryManager = this.MemoryManager, + ImageOperationsProvider = this.ImageOperationsProvider, + ReadOrigin = this.ReadOrigin, + +#if !NETSTANDARD1_1 + FileSystem = this.FileSystem +#endif + }; + } + + /// + /// Creates the default instance with the following s preregistered: + /// + /// + /// + /// + /// + /// The default configuration of + internal static Configuration CreateDefaultInstance() + { + return new Configuration( + new PngConfigurationModule(), + new JpegConfigurationModule(), + new GifConfigurationModule(), + new BmpConfigurationModule()); + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Formats/Bmp/BmpConfigurationModule.cs b/src/ImageSharp/Formats/Bmp/BmpConfigurationModule.cs index b091467bf..956acc157 100644 --- a/src/ImageSharp/Formats/Bmp/BmpConfigurationModule.cs +++ b/src/ImageSharp/Formats/Bmp/BmpConfigurationModule.cs @@ -11,9 +11,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// public void Configure(Configuration config) { - config.SetEncoder(ImageFormats.Bmp, new BmpEncoder()); - config.SetDecoder(ImageFormats.Bmp, new BmpDecoder()); - config.AddImageFormatDetector(new BmpImageFormatDetector()); + config.ImageFormatsManager.SetEncoder(ImageFormats.Bmp, new BmpEncoder()); + config.ImageFormatsManager.SetDecoder(ImageFormats.Bmp, new BmpDecoder()); + config.ImageFormatsManager.AddImageFormatDetector(new BmpImageFormatDetector()); } } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Bmp/ImageExtensions.cs b/src/ImageSharp/Formats/Bmp/ImageExtensions.cs index 935ce8f4a..35e168e27 100644 --- a/src/ImageSharp/Formats/Bmp/ImageExtensions.cs +++ b/src/ImageSharp/Formats/Bmp/ImageExtensions.cs @@ -36,6 +36,6 @@ namespace SixLabors.ImageSharp /// Thrown if the stream is null. public static void SaveAsBmp(this Image source, Stream stream, BmpEncoder encoder) where TPixel : struct, IPixel - => source.Save(stream, encoder ?? source.GetConfiguration().FindEncoder(ImageFormats.Bmp)); + => source.Save(stream, encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(ImageFormats.Bmp)); } } diff --git a/src/ImageSharp/Formats/Gif/GifConfigurationModule.cs b/src/ImageSharp/Formats/Gif/GifConfigurationModule.cs index 4c42a833c..0bb62779e 100644 --- a/src/ImageSharp/Formats/Gif/GifConfigurationModule.cs +++ b/src/ImageSharp/Formats/Gif/GifConfigurationModule.cs @@ -11,10 +11,10 @@ namespace SixLabors.ImageSharp.Formats.Gif /// public void Configure(Configuration config) { - config.SetEncoder(ImageFormats.Gif, new GifEncoder()); - config.SetDecoder(ImageFormats.Gif, new GifDecoder()); + config.ImageFormatsManager.SetEncoder(ImageFormats.Gif, new GifEncoder()); + config.ImageFormatsManager.SetDecoder(ImageFormats.Gif, new GifDecoder()); - config.AddImageFormatDetector(new GifImageFormatDetector()); + config.ImageFormatsManager.AddImageFormatDetector(new GifImageFormatDetector()); } } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Gif/ImageExtensions.cs b/src/ImageSharp/Formats/Gif/ImageExtensions.cs index 939eb456e..78acadb4b 100644 --- a/src/ImageSharp/Formats/Gif/ImageExtensions.cs +++ b/src/ImageSharp/Formats/Gif/ImageExtensions.cs @@ -36,6 +36,6 @@ namespace SixLabors.ImageSharp /// Thrown if the stream is null. public static void SaveAsGif(this Image source, Stream stream, GifEncoder encoder) where TPixel : struct, IPixel - => source.Save(stream, encoder ?? source.GetConfiguration().FindEncoder(ImageFormats.Gif)); + => source.Save(stream, encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(ImageFormats.Gif)); } } diff --git a/src/ImageSharp/Formats/ImageFormatManager.cs b/src/ImageSharp/Formats/ImageFormatManager.cs new file mode 100644 index 000000000..67ba11147 --- /dev/null +++ b/src/ImageSharp/Formats/ImageFormatManager.cs @@ -0,0 +1,186 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SixLabors.ImageSharp.Formats +{ + /// + /// Collection of Image Formats to be used in class. + /// + public class ImageFormatManager + { + /// + /// The list of supported keyed to mime types. + /// + private readonly ConcurrentDictionary mimeTypeEncoders = new ConcurrentDictionary(); + + /// + /// The list of supported keyed to mime types. + /// + private readonly ConcurrentDictionary mimeTypeDecoders = new ConcurrentDictionary(); + + /// + /// The list of supported s. + /// + private readonly ConcurrentBag imageFormats = new ConcurrentBag(); + + /// + /// The list of supported s. + /// + private ConcurrentBag imageFormatDetectors = new ConcurrentBag(); + + /// + /// Initializes a new instance of the class. + /// + public ImageFormatManager() + { + } + + /// + /// Gets the maximum header size of all the formats. + /// + internal int MaxHeaderSize { get; private set; } + + /// + /// Gets the currently registered s. + /// + public IEnumerable ImageFormats => this.imageFormats; + + /// + /// Gets the currently registered s. + /// + internal IEnumerable FormatDetectors => this.imageFormatDetectors; + + /// + /// Gets the currently registered s. + /// + internal IEnumerable> ImageDecoders => this.mimeTypeDecoders; + + /// + /// Gets the currently registered s. + /// + internal IEnumerable> ImageEncoders => this.mimeTypeEncoders; + + /// + /// Registers a new format provider. + /// + /// The format to register as a known format. + public void AddImageFormat(IImageFormat format) + { + Guard.NotNull(format, nameof(format)); + Guard.NotNull(format.MimeTypes, nameof(format.MimeTypes)); + Guard.NotNull(format.FileExtensions, nameof(format.FileExtensions)); + this.imageFormats.Add(format); + } + + /// + /// For the specified file extensions type find the e . + /// + /// The extension to discover + /// The if found otherwise null + public IImageFormat FindFormatByFileExtension(string extension) + { + return this.imageFormats.FirstOrDefault(x => x.FileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase)); + } + + /// + /// For the specified mime type find the . + /// + /// The mime-type to discover + /// The if found; otherwise null + public IImageFormat FindFormatByMimeType(string mimeType) + { + return this.imageFormats.FirstOrDefault(x => x.MimeTypes.Contains(mimeType, StringComparer.OrdinalIgnoreCase)); + } + + /// + /// Sets a specific image encoder as the encoder for a specific image format. + /// + /// The image format to register the encoder for. + /// The encoder to use, + public void SetEncoder(IImageFormat imageFormat, IImageEncoder encoder) + { + Guard.NotNull(imageFormat, nameof(imageFormat)); + Guard.NotNull(encoder, nameof(encoder)); + this.AddImageFormat(imageFormat); + this.mimeTypeEncoders.AddOrUpdate(imageFormat, encoder, (s, e) => encoder); + } + + /// + /// Sets a specific image decoder as the decoder for a specific image format. + /// + /// The image format to register the encoder for. + /// The decoder to use, + public void SetDecoder(IImageFormat imageFormat, IImageDecoder decoder) + { + Guard.NotNull(imageFormat, nameof(imageFormat)); + Guard.NotNull(decoder, nameof(decoder)); + this.AddImageFormat(imageFormat); + this.mimeTypeDecoders.AddOrUpdate(imageFormat, decoder, (s, e) => decoder); + } + + /// + /// Removes all the registered image format detectors. + /// + public void ClearImageFormatDetectors() + { + this.imageFormatDetectors = new ConcurrentBag(); + } + + /// + /// Adds a new detector for detecting mime types. + /// + /// The detector to add + public void AddImageFormatDetector(IImageFormatDetector detector) + { + Guard.NotNull(detector, nameof(detector)); + this.imageFormatDetectors.Add(detector); + this.SetMaxHeaderSize(); + } + + /// + /// For the specified mime type find the decoder. + /// + /// The format to discover + /// The if found otherwise null + public IImageDecoder FindDecoder(IImageFormat format) + { + Guard.NotNull(format, nameof(format)); + if (this.mimeTypeDecoders.TryGetValue(format, out IImageDecoder decoder)) + { + return decoder; + } + + return null; + } + + /// + /// For the specified mime type find the encoder. + /// + /// The format to discover + /// The if found otherwise null + public IImageEncoder FindEncoder(IImageFormat format) + { + Guard.NotNull(format, nameof(format)); + if (this.mimeTypeEncoders.TryGetValue(format, out IImageEncoder encoder)) + { + return encoder; + } + + return null; + } + + /// + /// Sets the max header size. + /// + private void SetMaxHeaderSize() + { + this.MaxHeaderSize = this.imageFormatDetectors.Max(x => x.HeaderSize); + } + } +} diff --git a/src/ImageSharp/Formats/Jpeg/ImageExtensions.cs b/src/ImageSharp/Formats/Jpeg/ImageExtensions.cs index 9cd7b3a8b..d3f95e40c 100644 --- a/src/ImageSharp/Formats/Jpeg/ImageExtensions.cs +++ b/src/ImageSharp/Formats/Jpeg/ImageExtensions.cs @@ -36,6 +36,6 @@ namespace SixLabors.ImageSharp /// Thrown if the stream is null. public static void SaveAsJpeg(this Image source, Stream stream, JpegEncoder encoder) where TPixel : struct, IPixel - => source.Save(stream, encoder ?? source.GetConfiguration().FindEncoder(ImageFormats.Jpeg)); + => source.Save(stream, encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(ImageFormats.Jpeg)); } } diff --git a/src/ImageSharp/Formats/Jpeg/JpegConfigurationModule.cs b/src/ImageSharp/Formats/Jpeg/JpegConfigurationModule.cs index 1ab509339..23cef5927 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegConfigurationModule.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegConfigurationModule.cs @@ -11,10 +11,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// public void Configure(Configuration config) { - config.SetEncoder(ImageFormats.Jpeg, new JpegEncoder()); - config.SetDecoder(ImageFormats.Jpeg, new JpegDecoder()); + config.ImageFormatsManager.SetEncoder(ImageFormats.Jpeg, new JpegEncoder()); + config.ImageFormatsManager.SetDecoder(ImageFormats.Jpeg, new JpegDecoder()); - config.AddImageFormatDetector(new JpegImageFormatDetector()); + config.ImageFormatsManager.AddImageFormatDetector(new JpegImageFormatDetector()); } } } diff --git a/src/ImageSharp/Formats/Png/ImageExtensions.cs b/src/ImageSharp/Formats/Png/ImageExtensions.cs index 10970fc16..f25d2bffe 100644 --- a/src/ImageSharp/Formats/Png/ImageExtensions.cs +++ b/src/ImageSharp/Formats/Png/ImageExtensions.cs @@ -35,6 +35,6 @@ namespace SixLabors.ImageSharp /// Thrown if the stream is null. public static void SaveAsPng(this Image source, Stream stream, PngEncoder encoder) where TPixel : struct, IPixel - => source.Save(stream, encoder ?? source.GetConfiguration().FindEncoder(ImageFormats.Png)); + => source.Save(stream, encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(ImageFormats.Png)); } } diff --git a/src/ImageSharp/Formats/Png/PngConfigurationModule.cs b/src/ImageSharp/Formats/Png/PngConfigurationModule.cs index ab6f31d49..0036280a8 100644 --- a/src/ImageSharp/Formats/Png/PngConfigurationModule.cs +++ b/src/ImageSharp/Formats/Png/PngConfigurationModule.cs @@ -11,9 +11,9 @@ namespace SixLabors.ImageSharp.Formats.Png /// public void Configure(Configuration config) { - config.SetEncoder(ImageFormats.Png, new PngEncoder()); - config.SetDecoder(ImageFormats.Png, new PngDecoder()); - config.AddImageFormatDetector(new PngImageFormatDetector()); + config.ImageFormatsManager.SetEncoder(ImageFormats.Png, new PngEncoder()); + config.ImageFormatsManager.SetDecoder(ImageFormats.Png, new PngDecoder()); + config.ImageFormatsManager.AddImageFormatDetector(new PngImageFormatDetector()); } } } \ No newline at end of file diff --git a/src/ImageSharp/Image/Image.Decode.cs b/src/ImageSharp/Image/Image.Decode.cs index 72492a494..6b44c893b 100644 --- a/src/ImageSharp/Image/Image.Decode.cs +++ b/src/ImageSharp/Image/Image.Decode.cs @@ -34,7 +34,7 @@ namespace SixLabors.ImageSharp long startPosition = stream.Position; stream.Read(buffer.Array, 0, maxHeaderSize); stream.Position = startPosition; - return config.FormatDetectors.Select(x => x.DetectFormat(buffer.Span)).LastOrDefault(x => x != null); + return config.ImageFormatsManager.FormatDetectors.Select(x => x.DetectFormat(buffer.Span)).LastOrDefault(x => x != null); } } @@ -50,7 +50,7 @@ namespace SixLabors.ImageSharp format = InternalDetectFormat(stream, config); if (format != null) { - return config.FindDecoder(format); + return config.ImageFormatsManager.FindDecoder(format); } return null; diff --git a/src/ImageSharp/Image/Image.FromStream.cs b/src/ImageSharp/Image/Image.FromStream.cs index 4e294260a..9061c334d 100644 --- a/src/ImageSharp/Image/Image.FromStream.cs +++ b/src/ImageSharp/Image/Image.FromStream.cs @@ -186,7 +186,7 @@ namespace SixLabors.ImageSharp var stringBuilder = new StringBuilder(); stringBuilder.AppendLine("Image cannot be loaded. Available decoders:"); - foreach (KeyValuePair val in config.ImageDecoders) + foreach (KeyValuePair val in config.ImageFormatsManager.ImageDecoders) { stringBuilder.AppendLine($" - {val.Key.Name} : {val.Value.GetType().Name}"); } diff --git a/src/ImageSharp/Image/ImageExtensions.cs b/src/ImageSharp/Image/ImageExtensions.cs index c4de1c298..7d23d95d9 100644 --- a/src/ImageSharp/Image/ImageExtensions.cs +++ b/src/ImageSharp/Image/ImageExtensions.cs @@ -32,7 +32,7 @@ namespace SixLabors.ImageSharp Guard.NotNullOrEmpty(filePath, nameof(filePath)); string ext = Path.GetExtension(filePath).Trim('.'); - IImageFormat format = source.GetConfiguration().FindFormatByFileExtension(ext); + IImageFormat format = source.GetConfiguration().ImageFormatsManager.FindFormatByFileExtension(ext); if (format == null) { var stringBuilder = new StringBuilder(); @@ -45,13 +45,13 @@ namespace SixLabors.ImageSharp throw new NotSupportedException(stringBuilder.ToString()); } - IImageEncoder encoder = source.GetConfiguration().FindEncoder(format); + IImageEncoder encoder = source.GetConfiguration().ImageFormatsManager.FindEncoder(format); if (encoder == null) { var stringBuilder = new StringBuilder(); stringBuilder.AppendLine($"Can't find encoder for file extention '{ext}' using image format '{format.Name}'. Registered encoders include:"); - foreach (KeyValuePair enc in source.GetConfiguration().ImageEncoders) + foreach (KeyValuePair enc in source.GetConfiguration().ImageFormatsManager.ImageEncoders) { stringBuilder.AppendLine($" - {enc.Key} : {enc.Value.GetType().Name}"); } @@ -93,14 +93,14 @@ namespace SixLabors.ImageSharp where TPixel : struct, IPixel { Guard.NotNull(format, nameof(format)); - IImageEncoder encoder = source.GetConfiguration().FindEncoder(format); + IImageEncoder encoder = source.GetConfiguration().ImageFormatsManager.FindEncoder(format); if (encoder == null) { var stringBuilder = new StringBuilder(); stringBuilder.AppendLine("Can't find encoder for provided mime type. Available encoded:"); - foreach (KeyValuePair val in source.GetConfiguration().ImageEncoders) + foreach (KeyValuePair val in source.GetConfiguration().ImageFormatsManager.ImageEncoders) { stringBuilder.AppendLine($" - {val.Key.Name} : {val.Value.GetType().Name}"); } diff --git a/tests/ImageSharp.Tests/ConfigurationTests.cs b/tests/ImageSharp.Tests/ConfigurationTests.cs index 06f02fcf1..cf348569c 100644 --- a/tests/ImageSharp.Tests/ConfigurationTests.cs +++ b/tests/ImageSharp.Tests/ConfigurationTests.cs @@ -22,8 +22,10 @@ namespace SixLabors.ImageSharp.Tests public Configuration DefaultConfiguration { get; private set; } public ConfigurationTests() - { - this.DefaultConfiguration = Configuration.CreateDefaultInstance(); + { + // the shallow copy of configuration should behave exactly like the default configuration, + // so by using the copy, we test both the default and the copy. + this.DefaultConfiguration = Configuration.CreateDefaultInstance().ShallowCopy(); this.ConfigurationEmpty = new Configuration(); } @@ -32,14 +34,7 @@ namespace SixLabors.ImageSharp.Tests { Assert.IsType(this.DefaultConfiguration.FileSystem); Assert.IsType(this.ConfigurationEmpty.FileSystem); - } - - [Fact] - public void IfAutoloadWellknwonFormatesIsTrueAllFormateAreLoaded() - { - Assert.Equal(4, this.DefaultConfiguration.ImageEncoders.Count()); - Assert.Equal(4, this.DefaultConfiguration.ImageDecoders.Count()); - } + } /// /// Test that the default configuration is not null. @@ -78,80 +73,6 @@ namespace SixLabors.ImageSharp.Tests Assert.True(Configuration.Default.ParallelOptions.MaxDegreeOfParallelism == Environment.ProcessorCount); } - [Fact] - public void AddImageFormatDetectorNullthrows() - { - Assert.Throws(() => - { - this.DefaultConfiguration.AddImageFormatDetector(null); - }); - } - - [Fact] - public void RegisterNullMimeTypeEncoder() - { - Assert.Throws(() => - { - this.DefaultConfiguration.SetEncoder(null, new Mock().Object); - }); - Assert.Throws(() => - { - this.DefaultConfiguration.SetEncoder(ImageFormats.Bmp, null); - }); - Assert.Throws(() => - { - this.DefaultConfiguration.SetEncoder(null, null); - }); - } - - [Fact] - public void RegisterNullSetDecoder() - { - Assert.Throws(() => - { - this.DefaultConfiguration.SetDecoder(null, new Mock().Object); - }); - Assert.Throws(() => - { - this.DefaultConfiguration.SetDecoder(ImageFormats.Bmp, null); - }); - Assert.Throws(() => - { - this.DefaultConfiguration.SetDecoder(null, null); - }); - } - - [Fact] - public void RegisterMimeTypeEncoderReplacesLast() - { - IImageEncoder encoder1 = new Mock().Object; - this.ConfigurationEmpty.SetEncoder(TestFormat.GlobalTestFormat, encoder1); - IImageEncoder found = this.ConfigurationEmpty.FindEncoder(TestFormat.GlobalTestFormat); - Assert.Equal(encoder1, found); - - IImageEncoder encoder2 = new Mock().Object; - this.ConfigurationEmpty.SetEncoder(TestFormat.GlobalTestFormat, encoder2); - IImageEncoder found2 = this.ConfigurationEmpty.FindEncoder(TestFormat.GlobalTestFormat); - Assert.Equal(encoder2, found2); - Assert.NotEqual(found, found2); - } - - [Fact] - public void RegisterMimeTypeDecoderReplacesLast() - { - IImageDecoder decoder1 = new Mock().Object; - this.ConfigurationEmpty.SetDecoder(TestFormat.GlobalTestFormat, decoder1); - IImageDecoder found = this.ConfigurationEmpty.FindDecoder(TestFormat.GlobalTestFormat); - Assert.Equal(decoder1, found); - - IImageDecoder decoder2 = new Mock().Object; - this.ConfigurationEmpty.SetDecoder(TestFormat.GlobalTestFormat, decoder2); - IImageDecoder found2 = this.ConfigurationEmpty.FindDecoder(TestFormat.GlobalTestFormat); - Assert.Equal(decoder2, found2); - Assert.NotEqual(found, found2); - } - - [Fact] public void ConstructorCallConfigureOnFormatProvider() { diff --git a/tests/ImageSharp.Tests/Formats/ImageFormatManagerTests.cs b/tests/ImageSharp.Tests/Formats/ImageFormatManagerTests.cs new file mode 100644 index 000000000..a6f6600f0 --- /dev/null +++ b/tests/ImageSharp.Tests/Formats/ImageFormatManagerTests.cs @@ -0,0 +1,129 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using SixLabors.ImageSharp.Formats; +using SixLabors.ImageSharp.IO; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Formats.Png; +using SixLabors.ImageSharp.Formats.Bmp; +using SixLabors.ImageSharp.Formats.Jpeg; +using SixLabors.ImageSharp.Formats.Gif; +using Moq; +using Xunit; + + +namespace SixLabors.ImageSharp.Tests +{ + public class ImageFormatManagerTests + { + public ImageFormatManager FormatsManagerEmpty { get; private set; } + public ImageFormatManager DefaultFormatsManager { get; private set; } + + public ImageFormatManagerTests() + { + this.DefaultFormatsManager = Configuration.Default.ImageFormatsManager; + this.FormatsManagerEmpty = new ImageFormatManager(); + } + + [Fact] + public void IfAutoloadWellKnownFormatsIsTrueAllFormatsAreLoaded() + { + Assert.Equal(1, this.DefaultFormatsManager.ImageEncoders.Select(item => item.Value).OfType().Count()); + Assert.Equal(1, this.DefaultFormatsManager.ImageEncoders.Select(item => item.Value).OfType().Count()); + Assert.Equal(1, this.DefaultFormatsManager.ImageEncoders.Select(item => item.Value).OfType().Count()); + Assert.Equal(1, this.DefaultFormatsManager.ImageEncoders.Select(item => item.Value).OfType().Count()); + + Assert.Equal(1, this.DefaultFormatsManager.ImageDecoders.Select(item => item.Value).OfType().Count()); + Assert.Equal(1, this.DefaultFormatsManager.ImageDecoders.Select(item => item.Value).OfType().Count()); + Assert.Equal(1, this.DefaultFormatsManager.ImageDecoders.Select(item => item.Value).OfType().Count()); + Assert.Equal(1, this.DefaultFormatsManager.ImageDecoders.Select(item => item.Value).OfType().Count()); + } + + [Fact] + public void AddImageFormatDetectorNullthrows() + { + Assert.Throws(() => + { + this.DefaultFormatsManager.AddImageFormatDetector(null); + }); + } + + [Fact] + public void RegisterNullMimeTypeEncoder() + { + Assert.Throws(() => + { + this.DefaultFormatsManager.SetEncoder(null, new Mock().Object); + }); + Assert.Throws(() => + { + this.DefaultFormatsManager.SetEncoder(ImageFormats.Bmp, null); + }); + Assert.Throws(() => + { + this.DefaultFormatsManager.SetEncoder(null, null); + }); + } + + [Fact] + public void RegisterNullSetDecoder() + { + Assert.Throws(() => + { + this.DefaultFormatsManager.SetDecoder(null, new Mock().Object); + }); + Assert.Throws(() => + { + this.DefaultFormatsManager.SetDecoder(ImageFormats.Bmp, null); + }); + Assert.Throws(() => + { + this.DefaultFormatsManager.SetDecoder(null, null); + }); + } + + [Fact] + public void RegisterMimeTypeEncoderReplacesLast() + { + IImageEncoder encoder1 = new Mock().Object; + this.FormatsManagerEmpty.SetEncoder(TestFormat.GlobalTestFormat, encoder1); + IImageEncoder found = this.FormatsManagerEmpty.FindEncoder(TestFormat.GlobalTestFormat); + Assert.Equal(encoder1, found); + + IImageEncoder encoder2 = new Mock().Object; + this.FormatsManagerEmpty.SetEncoder(TestFormat.GlobalTestFormat, encoder2); + IImageEncoder found2 = this.FormatsManagerEmpty.FindEncoder(TestFormat.GlobalTestFormat); + Assert.Equal(encoder2, found2); + Assert.NotEqual(found, found2); + } + + [Fact] + public void RegisterMimeTypeDecoderReplacesLast() + { + IImageDecoder decoder1 = new Mock().Object; + this.FormatsManagerEmpty.SetDecoder(TestFormat.GlobalTestFormat, decoder1); + IImageDecoder found = this.FormatsManagerEmpty.FindDecoder(TestFormat.GlobalTestFormat); + Assert.Equal(decoder1, found); + + IImageDecoder decoder2 = new Mock().Object; + this.FormatsManagerEmpty.SetDecoder(TestFormat.GlobalTestFormat, decoder2); + IImageDecoder found2 = this.FormatsManagerEmpty.FindDecoder(TestFormat.GlobalTestFormat); + Assert.Equal(decoder2, found2); + Assert.NotEqual(found, found2); + } + + [Fact] + public void AddFormatCallsConfig() + { + var provider = new Mock(); + var config = new Configuration(); + config.Configure(provider.Object); + + provider.Verify(x => x.Configure(config)); + } + } +} diff --git a/tests/ImageSharp.Tests/Image/ImageDiscoverMimeType.cs b/tests/ImageSharp.Tests/Image/ImageDiscoverMimeType.cs index f19fa1990..1a2275062 100644 --- a/tests/ImageSharp.Tests/Image/ImageDiscoverMimeType.cs +++ b/tests/ImageSharp.Tests/Image/ImageDiscoverMimeType.cs @@ -40,7 +40,7 @@ namespace SixLabors.ImageSharp.Tests FileSystem = this.fileSystem.Object }; - this.LocalConfiguration.AddImageFormatDetector(this.localMimeTypeDetector); + this.LocalConfiguration.ImageFormatsManager.AddImageFormatDetector(this.localMimeTypeDetector); TestFormat.RegisterGlobalTestFormat(); this.Marker = Guid.NewGuid().ToByteArray(); diff --git a/tests/ImageSharp.Tests/Image/ImageLoadTests.cs b/tests/ImageSharp.Tests/Image/ImageLoadTests.cs index de18714e2..97274e98b 100644 --- a/tests/ImageSharp.Tests/Image/ImageLoadTests.cs +++ b/tests/ImageSharp.Tests/Image/ImageLoadTests.cs @@ -54,8 +54,8 @@ namespace SixLabors.ImageSharp.Tests { FileSystem = this.fileSystem.Object }; - this.LocalConfiguration.AddImageFormatDetector(this.localMimeTypeDetector); - this.LocalConfiguration.SetDecoder(this.localImageFormatMock.Object, this.localDecoder.Object); + this.LocalConfiguration.ImageFormatsManager.AddImageFormatDetector(this.localMimeTypeDetector); + this.LocalConfiguration.ImageFormatsManager.SetDecoder(this.localImageFormatMock.Object, this.localDecoder.Object); TestFormat.RegisterGlobalTestFormat(); this.Marker = Guid.NewGuid().ToByteArray(); diff --git a/tests/ImageSharp.Tests/Image/ImageSaveTests.cs b/tests/ImageSharp.Tests/Image/ImageSaveTests.cs index 7f6e3b7da..028313e63 100644 --- a/tests/ImageSharp.Tests/Image/ImageSaveTests.cs +++ b/tests/ImageSharp.Tests/Image/ImageSaveTests.cs @@ -42,8 +42,8 @@ namespace SixLabors.ImageSharp.Tests { FileSystem = this.fileSystem.Object }; - config.AddImageFormatDetector(this.localMimeTypeDetector); - config.SetEncoder(this.localImageFormat.Object, this.encoder.Object); + config.ImageFormatsManager.AddImageFormatDetector(this.localMimeTypeDetector); + config.ImageFormatsManager.SetEncoder(this.localImageFormat.Object, this.encoder.Object); this.Image = new Image(config, 1, 1); } diff --git a/tests/ImageSharp.Tests/TestFormat.cs b/tests/ImageSharp.Tests/TestFormat.cs index 078b708df..445ace981 100644 --- a/tests/ImageSharp.Tests/TestFormat.cs +++ b/tests/ImageSharp.Tests/TestFormat.cs @@ -116,9 +116,9 @@ namespace SixLabors.ImageSharp.Tests public void Configure(Configuration host) { - host.AddImageFormatDetector(new TestHeader(this)); - host.SetEncoder(this, new TestEncoder(this)); - host.SetDecoder(this, new TestDecoder(this)); + host.ImageFormatsManager.AddImageFormatDetector(new TestHeader(this)); + host.ImageFormatsManager.SetEncoder(this, new TestEncoder(this)); + host.ImageFormatsManager.SetDecoder(this, new TestDecoder(this)); } public struct DecodeOperation diff --git a/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs b/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs index 089fed6b0..fa9497a8f 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs @@ -21,20 +21,20 @@ namespace SixLabors.ImageSharp.Tests internal static IImageDecoder GetReferenceDecoder(string filePath) { IImageFormat format = GetImageFormat(filePath); - return Configuration.FindDecoder(format); + return Configuration.ImageFormatsManager.FindDecoder(format); } internal static IImageEncoder GetReferenceEncoder(string filePath) { IImageFormat format = GetImageFormat(filePath); - return Configuration.FindEncoder(format); + return Configuration.ImageFormatsManager.FindEncoder(format); } internal static IImageFormat GetImageFormat(string filePath) { string extension = Path.GetExtension(filePath).ToLower(); if (extension[0] == '.') extension = extension.Substring(1); - IImageFormat format = Configuration.FindFormatByFileExtension(extension); + IImageFormat format = Configuration.ImageFormatsManager.FindFormatByFileExtension(extension); return format; } @@ -45,9 +45,9 @@ namespace SixLabors.ImageSharp.Tests IImageEncoder encoder, IImageFormatDetector detector) { - cfg.SetDecoder(imageFormat, decoder); - cfg.SetEncoder(imageFormat, encoder); - cfg.AddImageFormatDetector(detector); + cfg.ImageFormatsManager.SetDecoder(imageFormat, decoder); + cfg.ImageFormatsManager.SetEncoder(imageFormat, encoder); + cfg.ImageFormatsManager.AddImageFormatDetector(detector); } private static Configuration CreateDefaultConfiguration() diff --git a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs index 6014e2533..f03f9db09 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs @@ -360,7 +360,7 @@ namespace SixLabors.ImageSharp.Tests IImageDecoder referenceDecoder = TestEnvironment.GetReferenceDecoder(path); IImageFormat format = TestEnvironment.GetImageFormat(path); - IImageDecoder defaultDecoder = Configuration.Default.FindDecoder(format); + IImageDecoder defaultDecoder = Configuration.Default.ImageFormatsManager.FindDecoder(format); //if (referenceDecoder.GetType() == defaultDecoder.GetType()) //{