From bb9280f317528c5d8928acad0a730744f7d51f13 Mon Sep 17 00:00:00 2001 From: Scott Williams Date: Sun, 25 Jun 2017 18:03:59 +0100 Subject: [PATCH] switch from mimetype strings to IImageFormats --- .../ChangeDefaultEncoderOptions/Program.cs | 2 +- src/ImageSharp/Configuration.cs | 183 +++++++++--------- .../Formats/Bmp/BmpConfigurationModule.cs | 27 +++ src/ImageSharp/Formats/Bmp/BmpFormat.cs | 31 +++ ...eDetector.cs => BmpImageFormatDetector.cs} | 8 +- .../Formats/Bmp/BmpImageFormatProvider.cs | 45 ----- .../Formats/Gif/GifConfigurationModule.cs | 28 +++ src/ImageSharp/Formats/Gif/GifFormat.cs | 31 +++ ...eDetector.cs => GifImageFormatDetector.cs} | 8 +- .../Formats/Gif/GifImageFormatProvider.cs | 45 ----- src/ImageSharp/Formats/IImageFormat.cs | 39 ++++ ...ypeDetector.cs => IImageFormatDetector.cs} | 6 +- .../Formats/IImageFormatProvider.cs | 56 ------ .../Formats/Jpeg/JpegConfigurationModule.cs | 28 +++ src/ImageSharp/Formats/Jpeg/JpegFormat.cs | 31 +++ ...Detector.cs => JpegImageFormatDetector.cs} | 14 +- .../Formats/Jpeg/JpegImageFormatProvider.cs | 45 ----- .../Formats/Png/PngConfigurationModule.cs | 27 +++ src/ImageSharp/Formats/Png/PngFormat.cs | 31 +++ ...eDetector.cs => PngImageFormatDetector.cs} | 10 +- .../Formats/Png/PngImageFormatProvider.cs | 45 ----- src/ImageSharp/IConfigurationModule.cs | 23 +++ src/ImageSharp/Image/Image.Decode.cs | 31 ++- src/ImageSharp/Image/Image.FromBytes.cs | 34 ++-- src/ImageSharp/Image/Image.FromFile.cs | 28 +-- src/ImageSharp/Image/Image.FromStream.cs | 36 ++-- src/ImageSharp/Image/Image{TPixel}.cs | 52 ++--- src/ImageSharp/ImageFormats.cs | 39 ++++ src/ImageSharp/Memory/Buffer.cs | 10 + tests/ImageSharp.Tests/ConfigurationTests.cs | 76 +++----- .../Formats/GeneralFormatTests.cs | 6 +- .../Image/ImageDiscoverMimeType.cs | 56 +++--- .../ImageSharp.Tests/Image/ImageLoadTests.cs | 14 +- .../ImageSharp.Tests/Image/ImageSaveTests.cs | 19 +- tests/ImageSharp.Tests/Image/ImageTests.cs | 4 +- tests/ImageSharp.Tests/TestFormat.cs | 33 ++-- .../TestUtilities/ImagingTestCaseUtility.cs | 4 +- 37 files changed, 647 insertions(+), 558 deletions(-) create mode 100644 src/ImageSharp/Formats/Bmp/BmpConfigurationModule.cs create mode 100644 src/ImageSharp/Formats/Bmp/BmpFormat.cs rename src/ImageSharp/Formats/Bmp/{BmpMimeTypeDetector.cs => BmpImageFormatDetector.cs} (77%) delete mode 100644 src/ImageSharp/Formats/Bmp/BmpImageFormatProvider.cs create mode 100644 src/ImageSharp/Formats/Gif/GifConfigurationModule.cs create mode 100644 src/ImageSharp/Formats/Gif/GifFormat.cs rename src/ImageSharp/Formats/Gif/{GifMimeTypeDetector.cs => GifImageFormatDetector.cs} (81%) delete mode 100644 src/ImageSharp/Formats/Gif/GifImageFormatProvider.cs create mode 100644 src/ImageSharp/Formats/IImageFormat.cs rename src/ImageSharp/Formats/{IMimeTypeDetector.cs => IImageFormatDetector.cs} (81%) delete mode 100644 src/ImageSharp/Formats/IImageFormatProvider.cs create mode 100644 src/ImageSharp/Formats/Jpeg/JpegConfigurationModule.cs create mode 100644 src/ImageSharp/Formats/Jpeg/JpegFormat.cs rename src/ImageSharp/Formats/Jpeg/{JpegMimeTypeDetector.cs => JpegImageFormatDetector.cs} (85%) delete mode 100644 src/ImageSharp/Formats/Jpeg/JpegImageFormatProvider.cs create mode 100644 src/ImageSharp/Formats/Png/PngConfigurationModule.cs create mode 100644 src/ImageSharp/Formats/Png/PngFormat.cs rename src/ImageSharp/Formats/Png/{PngMimeTypeDetector.cs => PngImageFormatDetector.cs} (76%) delete mode 100644 src/ImageSharp/Formats/Png/PngImageFormatProvider.cs create mode 100644 src/ImageSharp/IConfigurationModule.cs create mode 100644 src/ImageSharp/ImageFormats.cs diff --git a/samples/ChangeDefaultEncoderOptions/Program.cs b/samples/ChangeDefaultEncoderOptions/Program.cs index b085e468a1..dab8d445ca 100644 --- a/samples/ChangeDefaultEncoderOptions/Program.cs +++ b/samples/ChangeDefaultEncoderOptions/Program.cs @@ -10,7 +10,7 @@ namespace ChangeDefaultEncoderOptions { // lets switch out the default encoder for jpeg to one // that saves at 90 quality and ignores the matadata - Configuration.Default.SetMimeTypeEncoder("image/jpeg", new ImageSharp.Formats.JpegEncoder() + Configuration.Default.SetEncoder(ImageFormats.Jpeg, new ImageSharp.Formats.JpegEncoder() { Quality = 90, IgnoreMetadata = true diff --git a/src/ImageSharp/Configuration.cs b/src/ImageSharp/Configuration.cs index f48aefbcd8..90fd3a0e66 100644 --- a/src/ImageSharp/Configuration.cs +++ b/src/ImageSharp/Configuration.cs @@ -18,7 +18,7 @@ namespace ImageSharp /// /// Provides initialization code which allows extending the library. /// - public class Configuration : IImageFormatHost + public class Configuration { /// /// A lazily initialized configuration default instance. @@ -33,22 +33,22 @@ namespace ImageSharp /// /// The list of supported keyed to mime types. /// - private readonly ConcurrentDictionary mimeTypeEncoders = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); + private readonly ConcurrentDictionary mimeTypeEncoders = new ConcurrentDictionary(); /// - /// The list of supported mime types keyed to file extensions. + /// The list of supported keyed to mime types. /// - private readonly ConcurrentDictionary extensionsMap = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); + private readonly ConcurrentDictionary mimeTypeDecoders = new ConcurrentDictionary(); /// - /// The list of supported keyed to mime types. + /// The list of supported s. /// - private readonly ConcurrentDictionary mimeTypeDecoders = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); + private readonly List imageFormatDetectors = new List(); /// - /// The list of supported s. + /// The list of supported s. /// - private readonly List mimeTypeDetectors = new List(); + private readonly HashSet imageFormats = new HashSet(); /// /// Initializes a new instance of the class. @@ -61,11 +61,11 @@ namespace ImageSharp /// Initializes a new instance of the class. /// /// A collection of providers to configure - public Configuration(params IImageFormatProvider[] providers) + public Configuration(params IConfigurationModule[] providers) { if (providers != null) { - foreach (IImageFormatProvider p in providers) + foreach (IConfigurationModule p in providers) { p.Configure(this); } @@ -88,24 +88,24 @@ namespace ImageSharp internal int MaxHeaderSize { get; private set; } /// - /// Gets the currently registered s. + /// Gets the currently registered s. /// - internal IEnumerable MimeTypeDetectors => this.mimeTypeDetectors; + internal IEnumerable FormatDetectors => this.imageFormatDetectors; /// /// Gets the currently registered s. /// - internal IEnumerable> ImageDecoders => this.mimeTypeDecoders; + internal IEnumerable> ImageDecoders => this.mimeTypeDecoders; /// /// Gets the currently registered s. /// - internal IEnumerable> ImageEncoders => this.mimeTypeEncoders; + internal IEnumerable> ImageEncoders => this.mimeTypeEncoders; /// - /// Gets the currently registered file extensions. + /// Gets the currently registered s. /// - internal IEnumerable> ImageExtensionToMimeTypeMapping => this.extensionsMap; + internal IEnumerable ImageFormats => this.imageFormats; #if !NETSTANDARD1_1 /// @@ -117,35 +117,69 @@ namespace ImageSharp /// /// Registers a new format provider. /// - /// The format providers to call configure on. - public void AddImageFormat(IImageFormatProvider formatProvider) + /// The configuration provider to call configure on. + public void Configure(IConfigurationModule configuration) { - Guard.NotNull(formatProvider, nameof(formatProvider)); - formatProvider.Configure(this); + Guard.NotNull(configuration, nameof(configuration)); + configuration.Configure(this); } - /// - public void SetMimeTypeEncoder(string mimeType, IImageEncoder encoder) + /// + /// Registers a new format provider. + /// + /// The format to register as a well know format. + public void AddImageFormat(IImageFormat format) { - Guard.NotNullOrEmpty(mimeType, nameof(mimeType)); - Guard.NotNull(encoder, nameof(encoder)); - this.mimeTypeEncoders.AddOrUpdate(mimeType?.Trim(), encoder, (s, e) => encoder); + 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 FindFormatByFileExtensions(string extension) + { + return this.imageFormats.FirstOrDefault(x => x.FileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase)); } - /// - public void SetFileExtensionToMimeTypeMapping(string extension, string mimeType) + /// + /// For the specified mime type find the . + /// + /// The mime-type to discover + /// The if found otherwise null + public IImageFormat FindFormatByMimeType(string mimeType) { - Guard.NotNullOrEmpty(extension, nameof(extension)); - Guard.NotNullOrEmpty(mimeType, nameof(mimeType)); - this.extensionsMap.AddOrUpdate(extension?.Trim(), mimeType, (s, e) => mimeType); + return this.imageFormats.FirstOrDefault(x => x.MimeTypes.Contains(mimeType, StringComparer.OrdinalIgnoreCase)); } - /// - public void SetMimeTypeDecoder(string mimeType, IImageDecoder decoder) + /// + /// 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.NotNullOrEmpty(mimeType, nameof(mimeType)); + 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.mimeTypeDecoders.AddOrUpdate(mimeType, decoder, (s, e) => decoder); + this.AddImageFormat(imageFormat); + this.mimeTypeDecoders.AddOrUpdate(imageFormat, decoder, (s, e) => decoder); } /// @@ -153,43 +187,46 @@ namespace ImageSharp /// public void ClearMimeTypeDetectors() { - this.mimeTypeDetectors.Clear(); + this.imageFormatDetectors.Clear(); } - /// - public void AddMimeTypeDetector(IMimeTypeDetector detector) + /// + /// Adds a new detector for detecting mime types. + /// + /// The detector to add + public void AddImageFormatDetector(IImageFormatDetector detector) { Guard.NotNull(detector, nameof(detector)); - this.mimeTypeDetectors.Add(detector); + this.imageFormatDetectors.Add(detector); this.SetMaxHeaderSize(); } /// - /// Creates the default instance with the following s preregistered: - /// - /// - /// - /// + /// Creates the default instance with the following s preregistered: + /// + /// + /// + /// /// /// The default configuration of internal static Configuration CreateDefaultInstance() { return new Configuration( - new PngImageFormatProvider(), - new JpegImageFormatProvider(), - new GifImageFormatProvider(), - new BmpImageFormatProvider()); + new PngConfigurationModule(), + new JpegConfigurationModule(), + new GifConfigurationModule(), + new BmpConfigurationModule()); } /// /// For the specified mime type find the decoder. /// - /// The mime type to discover + /// The format to discover /// The if found otherwise null - internal IImageDecoder FindMimeTypeDecoder(string mimeType) + internal IImageDecoder FindDecoder(IImageFormat format) { - Guard.NotNullOrEmpty(mimeType, nameof(mimeType)); - if (this.mimeTypeDecoders.TryGetValue(mimeType, out IImageDecoder decoder)) + Guard.NotNull(format, nameof(format)); + if (this.mimeTypeDecoders.TryGetValue(format, out IImageDecoder decoder)) { return decoder; } @@ -200,12 +237,12 @@ namespace ImageSharp /// /// For the specified mime type find the encoder. /// - /// The mime type to discover + /// The format to discover /// The if found otherwise null - internal IImageEncoder FindMimeTypeEncoder(string mimeType) + internal IImageEncoder FindEncoder(IImageFormat format) { - Guard.NotNullOrEmpty(mimeType, nameof(mimeType)); - if (this.mimeTypeEncoders.TryGetValue(mimeType, out IImageEncoder encoder)) + Guard.NotNull(format, nameof(format)); + if (this.mimeTypeEncoders.TryGetValue(format, out IImageEncoder encoder)) { return encoder; } @@ -213,46 +250,12 @@ namespace ImageSharp return null; } - /// - /// For the specified mime type find the encoder. - /// - /// The extensions to discover - /// The if found otherwise null - internal IImageEncoder FindFileExtensionsEncoder(string extensions) - { - extensions = extensions?.TrimStart('.'); - Guard.NotNullOrEmpty(extensions, nameof(extensions)); - if (this.extensionsMap.TryGetValue(extensions, out string mimeType)) - { - return this.FindMimeTypeEncoder(mimeType); - } - - return null; - } - - /// - /// For the specified extension find the mime type. - /// - /// the extensions to discover - /// The mime type if found otherwise null - internal string FindFileExtensionsMimeType(string extensions) - { - extensions = extensions?.TrimStart('.'); - Guard.NotNullOrEmpty(extensions, nameof(extensions)); - if (this.extensionsMap.TryGetValue(extensions, out string mimeType)) - { - return mimeType; - } - - return null; - } - /// /// Sets the max header size. /// private void SetMaxHeaderSize() { - this.MaxHeaderSize = this.mimeTypeDetectors.Max(x => x.HeaderSize); + this.MaxHeaderSize = this.imageFormatDetectors.Max(x => x.HeaderSize); } } } diff --git a/src/ImageSharp/Formats/Bmp/BmpConfigurationModule.cs b/src/ImageSharp/Formats/Bmp/BmpConfigurationModule.cs new file mode 100644 index 0000000000..2553f14542 --- /dev/null +++ b/src/ImageSharp/Formats/Bmp/BmpConfigurationModule.cs @@ -0,0 +1,27 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Formats +{ + using System; + using System.Collections.Generic; + using System.IO; + using System.Text; + using ImageSharp.PixelFormats; + + /// + /// Registers the image encoders, decoders and mime type detectors for the bmp format. + /// + public class BmpConfigurationModule : IConfigurationModule + { + /// + public void Configure(Configuration config) + { + config.SetEncoder(ImageFormats.Bitmap, new BmpEncoder()); + config.SetDecoder(ImageFormats.Bitmap, new BmpDecoder()); + config.AddImageFormatDetector(new BmpImageFormatDetector()); + } + } +} diff --git a/src/ImageSharp/Formats/Bmp/BmpFormat.cs b/src/ImageSharp/Formats/Bmp/BmpFormat.cs new file mode 100644 index 0000000000..4f32e2875e --- /dev/null +++ b/src/ImageSharp/Formats/Bmp/BmpFormat.cs @@ -0,0 +1,31 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Formats +{ + using System; + using System.Collections.Generic; + using System.IO; + using System.Text; + using ImageSharp.PixelFormats; + + /// + /// Registers the image encoders, decoders and mime type detectors for the jpeg format. + /// + internal sealed class BmpFormat : IImageFormat + { + /// + public string Name => "BMP"; + + /// + public string DefaultMimeType => "image/bmp"; + + /// + public IEnumerable MimeTypes => BmpConstants.MimeTypes; + + /// + public IEnumerable FileExtensions => BmpConstants.FileExtensions; + } +} diff --git a/src/ImageSharp/Formats/Bmp/BmpMimeTypeDetector.cs b/src/ImageSharp/Formats/Bmp/BmpImageFormatDetector.cs similarity index 77% rename from src/ImageSharp/Formats/Bmp/BmpMimeTypeDetector.cs rename to src/ImageSharp/Formats/Bmp/BmpImageFormatDetector.cs index c13181d6a2..4f1054b097 100644 --- a/src/ImageSharp/Formats/Bmp/BmpMimeTypeDetector.cs +++ b/src/ImageSharp/Formats/Bmp/BmpImageFormatDetector.cs @@ -14,23 +14,23 @@ namespace ImageSharp.Formats /// /// Detects bmp file headers /// - internal class BmpMimeTypeDetector : IMimeTypeDetector + internal class BmpImageFormatDetector : IImageFormatDetector { /// public int HeaderSize => 2; /// - public string DetectMimeType(Span header) + public IImageFormat DetectFormat(ReadOnlySpan header) { if (this.IsSupportedFileFormat(header)) { - return "image/bmp"; + return ImageFormats.Bitmap; } return null; } - private bool IsSupportedFileFormat(Span header) + private bool IsSupportedFileFormat(ReadOnlySpan header) { return header.Length >= this.HeaderSize && header[0] == 0x42 && // B diff --git a/src/ImageSharp/Formats/Bmp/BmpImageFormatProvider.cs b/src/ImageSharp/Formats/Bmp/BmpImageFormatProvider.cs deleted file mode 100644 index b532ccfb51..0000000000 --- a/src/ImageSharp/Formats/Bmp/BmpImageFormatProvider.cs +++ /dev/null @@ -1,45 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - using System; - using System.Collections.Generic; - using System.IO; - using System.Text; - using ImageSharp.PixelFormats; - - /// - /// Registers the image encoders, decoders and mime type detectors for the bmp format. - /// - public class BmpImageFormatProvider : IImageFormatProvider - { - /// - public void Configure(IImageFormatHost host) - { - var encoder = new BmpEncoder(); - foreach (string mimeType in BmpConstants.MimeTypes) - { - host.SetMimeTypeEncoder(mimeType, encoder); - } - - foreach (string ext in BmpConstants.FileExtensions) - { - foreach (string mimeType in BmpConstants.MimeTypes) - { - host.SetFileExtensionToMimeTypeMapping(ext, mimeType); - } - } - - var decoder = new BmpDecoder(); - foreach (string mimeType in BmpConstants.MimeTypes) - { - host.SetMimeTypeDecoder(mimeType, decoder); - } - - host.AddMimeTypeDetector(new BmpMimeTypeDetector()); - } - } -} diff --git a/src/ImageSharp/Formats/Gif/GifConfigurationModule.cs b/src/ImageSharp/Formats/Gif/GifConfigurationModule.cs new file mode 100644 index 0000000000..0640cb2347 --- /dev/null +++ b/src/ImageSharp/Formats/Gif/GifConfigurationModule.cs @@ -0,0 +1,28 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Formats +{ + using System; + using System.Collections.Generic; + using System.IO; + using System.Text; + using ImageSharp.PixelFormats; + + /// + /// Registers the image encoders, decoders and mime type detectors for the gif format. + /// + public class GifConfigurationModule : IConfigurationModule + { + /// + public void Configure(Configuration config) + { + config.SetEncoder(ImageFormats.Gif, new GifEncoder()); + config.SetDecoder(ImageFormats.Gif, new GifDecoder()); + + config.AddImageFormatDetector(new GifImageFormatDetector()); + } + } +} diff --git a/src/ImageSharp/Formats/Gif/GifFormat.cs b/src/ImageSharp/Formats/Gif/GifFormat.cs new file mode 100644 index 0000000000..5aa667ea91 --- /dev/null +++ b/src/ImageSharp/Formats/Gif/GifFormat.cs @@ -0,0 +1,31 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Formats +{ + using System; + using System.Collections.Generic; + using System.IO; + using System.Text; + using ImageSharp.PixelFormats; + + /// + /// Registers the image encoders, decoders and mime type detectors for the jpeg format. + /// + internal sealed class GifFormat : IImageFormat + { + /// + public string Name => "GIF"; + + /// + public string DefaultMimeType => "image/gif"; + + /// + public IEnumerable MimeTypes => GifConstants.MimeTypes; + + /// + public IEnumerable FileExtensions => GifConstants.FileExtensions; + } +} diff --git a/src/ImageSharp/Formats/Gif/GifMimeTypeDetector.cs b/src/ImageSharp/Formats/Gif/GifImageFormatDetector.cs similarity index 81% rename from src/ImageSharp/Formats/Gif/GifMimeTypeDetector.cs rename to src/ImageSharp/Formats/Gif/GifImageFormatDetector.cs index f4ad8fa8e1..2aee867953 100644 --- a/src/ImageSharp/Formats/Gif/GifMimeTypeDetector.cs +++ b/src/ImageSharp/Formats/Gif/GifImageFormatDetector.cs @@ -14,23 +14,23 @@ namespace ImageSharp.Formats /// /// Detects gif file headers /// - public class GifMimeTypeDetector : IMimeTypeDetector + public class GifImageFormatDetector : IImageFormatDetector { /// public int HeaderSize => 6; /// - public string DetectMimeType(Span header) + public IImageFormat DetectFormat(ReadOnlySpan header) { if (this.IsSupportedFileFormat(header)) { - return "image/gif"; + return ImageFormats.Gif; } return null; } - private bool IsSupportedFileFormat(Span header) + private bool IsSupportedFileFormat(ReadOnlySpan header) { return header.Length >= this.HeaderSize && header[0] == 0x47 && // G diff --git a/src/ImageSharp/Formats/Gif/GifImageFormatProvider.cs b/src/ImageSharp/Formats/Gif/GifImageFormatProvider.cs deleted file mode 100644 index 7e16bff720..0000000000 --- a/src/ImageSharp/Formats/Gif/GifImageFormatProvider.cs +++ /dev/null @@ -1,45 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - using System; - using System.Collections.Generic; - using System.IO; - using System.Text; - using ImageSharp.PixelFormats; - - /// - /// Registers the image encoders, decoders and mime type detectors for the gif format. - /// - public class GifImageFormatProvider : IImageFormatProvider - { - /// - public void Configure(IImageFormatHost host) - { - var encoder = new GifEncoder(); - foreach (string mimeType in GifConstants.MimeTypes) - { - host.SetMimeTypeEncoder(mimeType, encoder); - } - - foreach (string ext in GifConstants.FileExtensions) - { - foreach (string mimeType in GifConstants.MimeTypes) - { - host.SetFileExtensionToMimeTypeMapping(ext, mimeType); - } - } - - var decoder = new GifDecoder(); - foreach (string mimeType in GifConstants.MimeTypes) - { - host.SetMimeTypeDecoder(mimeType, decoder); - } - - host.AddMimeTypeDetector(new GifMimeTypeDetector()); - } - } -} diff --git a/src/ImageSharp/Formats/IImageFormat.cs b/src/ImageSharp/Formats/IImageFormat.cs new file mode 100644 index 0000000000..8643e2f4c9 --- /dev/null +++ b/src/ImageSharp/Formats/IImageFormat.cs @@ -0,0 +1,39 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Formats +{ + using System; + using System.Collections.Generic; + using System.IO; + + using ImageSharp.PixelFormats; + + /// + /// Describes an image format. + /// + public interface IImageFormat + { + /// + /// Gets the name that describes this image format. + /// + string Name { get; } + + /// + /// Gets the default mimetype that the image foramt uses + /// + string DefaultMimeType { get; } + + /// + /// Gets all the mimetypes that have been used by this image foramt. + /// + IEnumerable MimeTypes { get; } + + /// + /// Gets the file extensions this image format commonly uses. + /// + IEnumerable FileExtensions { get; } + } +} diff --git a/src/ImageSharp/Formats/IMimeTypeDetector.cs b/src/ImageSharp/Formats/IImageFormatDetector.cs similarity index 81% rename from src/ImageSharp/Formats/IMimeTypeDetector.cs rename to src/ImageSharp/Formats/IImageFormatDetector.cs index f55be71516..a53da07e8b 100644 --- a/src/ImageSharp/Formats/IMimeTypeDetector.cs +++ b/src/ImageSharp/Formats/IImageFormatDetector.cs @@ -1,4 +1,4 @@ -// +// // Copyright (c) James Jackson-South and contributors. // Licensed under the Apache License, Version 2.0. // @@ -12,7 +12,7 @@ namespace ImageSharp.Formats /// /// Used for detecting mime types from a file header /// - public interface IMimeTypeDetector + public interface IImageFormatDetector { /// /// Gets the size of the header for this image type. @@ -25,6 +25,6 @@ namespace ImageSharp.Formats /// /// The containing the file header. /// returns the mime type of detected othersie returns null - string DetectMimeType(Span header); + IImageFormat DetectFormat(ReadOnlySpan header); } } diff --git a/src/ImageSharp/Formats/IImageFormatProvider.cs b/src/ImageSharp/Formats/IImageFormatProvider.cs deleted file mode 100644 index 1e5ea7f93e..0000000000 --- a/src/ImageSharp/Formats/IImageFormatProvider.cs +++ /dev/null @@ -1,56 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - using System; - using System.Collections.Generic; - using System.Text; - - /// - /// Represents an interface that can register image encoders, decoders and mime type detectors. - /// - public interface IImageFormatProvider - { - /// - /// Called when loaded so the provider and register its encoders, decoders and mime type detectors into an IImageFormatHost. - /// - /// The host that will retain the encoders, decodes and mime type detectors. - void Configure(IImageFormatHost host); - } - - /// - /// Represents an interface that can have encoders, decoders and mime type detectors loaded into. - /// - public interface IImageFormatHost - { - /// - /// Sets a specific image encoder as the encoder for a specific mime type. - /// - /// the target mimetype - /// the encoder to use - void SetMimeTypeEncoder(string mimeType, IImageEncoder encoder); // could/should this be an Action??? - - /// - /// Sets a mapping value between a file extension and a mime type. - /// - /// The target mime type - /// The mime type this extension equates to - void SetFileExtensionToMimeTypeMapping(string extension, string mimetype); - - /// - /// Sets a specific image decoder as the decoder for a specific mime type. - /// - /// The target mime type - /// The decoder to use - void SetMimeTypeDecoder(string mimeType, IImageDecoder decoder); - - /// - /// Adds a new detector for detecting mime types. - /// - /// The detector to add - void AddMimeTypeDetector(IMimeTypeDetector detector); - } -} diff --git a/src/ImageSharp/Formats/Jpeg/JpegConfigurationModule.cs b/src/ImageSharp/Formats/Jpeg/JpegConfigurationModule.cs new file mode 100644 index 0000000000..64c7af3579 --- /dev/null +++ b/src/ImageSharp/Formats/Jpeg/JpegConfigurationModule.cs @@ -0,0 +1,28 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Formats +{ + using System; + using System.Collections.Generic; + using System.IO; + using System.Text; + using ImageSharp.PixelFormats; + + /// + /// Registers the image encoders, decoders and mime type detectors for the jpeg format. + /// + public class JpegConfigurationModule : IConfigurationModule + { + /// + public void Configure(Configuration config) + { + config.SetEncoder(ImageFormats.Jpeg, new JpegEncoder()); + config.SetDecoder(ImageFormats.Jpeg, new JpegDecoder()); + + config.AddImageFormatDetector(new JpegImageFormatDetector()); + } + } +} diff --git a/src/ImageSharp/Formats/Jpeg/JpegFormat.cs b/src/ImageSharp/Formats/Jpeg/JpegFormat.cs new file mode 100644 index 0000000000..86b624fc85 --- /dev/null +++ b/src/ImageSharp/Formats/Jpeg/JpegFormat.cs @@ -0,0 +1,31 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Formats +{ + using System; + using System.Collections.Generic; + using System.IO; + using System.Text; + using ImageSharp.PixelFormats; + + /// + /// Registers the image encoders, decoders and mime type detectors for the jpeg format. + /// + internal sealed class JpegFormat : IImageFormat + { + /// + public string Name => "JPEG"; + + /// + public string DefaultMimeType => "image/jpeg"; + + /// + public IEnumerable MimeTypes => JpegConstants.MimeTypes; + + /// + public IEnumerable FileExtensions => JpegConstants.FileExtensions; + } +} diff --git a/src/ImageSharp/Formats/Jpeg/JpegMimeTypeDetector.cs b/src/ImageSharp/Formats/Jpeg/JpegImageFormatDetector.cs similarity index 85% rename from src/ImageSharp/Formats/Jpeg/JpegMimeTypeDetector.cs rename to src/ImageSharp/Formats/Jpeg/JpegImageFormatDetector.cs index f84a91f70c..82f810625f 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegMimeTypeDetector.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegImageFormatDetector.cs @@ -14,23 +14,23 @@ namespace ImageSharp.Formats /// /// Detects Jpeg file headers /// - public class JpegMimeTypeDetector : IMimeTypeDetector + public class JpegImageFormatDetector : IImageFormatDetector { /// public int HeaderSize => 11; /// - public string DetectMimeType(Span header) + public IImageFormat DetectFormat(ReadOnlySpan header) { if (this.IsSupportedFileFormat(header)) { - return "image/jpeg"; + return ImageFormats.Jpeg; } return null; } - private bool IsSupportedFileFormat(Span header) + private bool IsSupportedFileFormat(ReadOnlySpan header) { return header.Length >= this.HeaderSize && (this.IsJfif(header) || this.IsExif(header) || this.IsJpeg(header)); @@ -41,7 +41,7 @@ namespace ImageSharp.Formats /// /// The bytes representing the file header. /// The - private bool IsJfif(Span header) + private bool IsJfif(ReadOnlySpan header) { bool isJfif = header[6] == 0x4A && // J @@ -58,7 +58,7 @@ namespace ImageSharp.Formats /// /// The bytes representing the file header. /// The - private bool IsExif(Span header) + private bool IsExif(ReadOnlySpan header) { bool isExif = header[6] == 0x45 && // E @@ -76,7 +76,7 @@ namespace ImageSharp.Formats /// /// The bytes representing the file header. /// The - private bool IsJpeg(Span header) + private bool IsJpeg(ReadOnlySpan header) { bool isJpg = header[0] == 0xFF && // 255 diff --git a/src/ImageSharp/Formats/Jpeg/JpegImageFormatProvider.cs b/src/ImageSharp/Formats/Jpeg/JpegImageFormatProvider.cs deleted file mode 100644 index 5eefa5db16..0000000000 --- a/src/ImageSharp/Formats/Jpeg/JpegImageFormatProvider.cs +++ /dev/null @@ -1,45 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - using System; - using System.Collections.Generic; - using System.IO; - using System.Text; - using ImageSharp.PixelFormats; - - /// - /// Registers the image encoders, decoders and mime type detectors for the jpeg format. - /// - public class JpegImageFormatProvider : IImageFormatProvider - { - /// - public void Configure(IImageFormatHost host) - { - var pngEncoder = new JpegEncoder(); - foreach (string mimeType in JpegConstants.MimeTypes) - { - host.SetMimeTypeEncoder(mimeType, pngEncoder); - } - - foreach (string ext in JpegConstants.FileExtensions) - { - foreach (string mimeType in JpegConstants.MimeTypes) - { - host.SetFileExtensionToMimeTypeMapping(ext, mimeType); - } - } - - var pngDecoder = new JpegDecoder(); - foreach (string mimeType in JpegConstants.MimeTypes) - { - host.SetMimeTypeDecoder(mimeType, pngDecoder); - } - - host.AddMimeTypeDetector(new JpegMimeTypeDetector()); - } - } -} diff --git a/src/ImageSharp/Formats/Png/PngConfigurationModule.cs b/src/ImageSharp/Formats/Png/PngConfigurationModule.cs new file mode 100644 index 0000000000..47fe8b136a --- /dev/null +++ b/src/ImageSharp/Formats/Png/PngConfigurationModule.cs @@ -0,0 +1,27 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Formats +{ + using System; + using System.Collections.Generic; + using System.IO; + using System.Text; + using ImageSharp.PixelFormats; + + /// + /// Registers the image encoders, decoders and mime type detectors for the png format. + /// + public class PngConfigurationModule : IConfigurationModule + { + /// + public void Configure(Configuration host) + { + host.SetEncoder(ImageFormats.Png, new PngEncoder()); + host.SetDecoder(ImageFormats.Png, new PngDecoder()); + host.AddImageFormatDetector(new PngImageFormatDetector()); + } + } +} diff --git a/src/ImageSharp/Formats/Png/PngFormat.cs b/src/ImageSharp/Formats/Png/PngFormat.cs new file mode 100644 index 0000000000..60ba306056 --- /dev/null +++ b/src/ImageSharp/Formats/Png/PngFormat.cs @@ -0,0 +1,31 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Formats +{ + using System; + using System.Collections.Generic; + using System.IO; + using System.Text; + using ImageSharp.PixelFormats; + + /// + /// Registers the image encoders, decoders and mime type detectors for the jpeg format. + /// + internal sealed class PngFormat : IImageFormat + { + /// + public string Name => "PNG"; + + /// + public string DefaultMimeType => "image/png"; + + /// + public IEnumerable MimeTypes => PngConstants.MimeTypes; + + /// + public IEnumerable FileExtensions => PngConstants.FileExtensions; + } +} diff --git a/src/ImageSharp/Formats/Png/PngMimeTypeDetector.cs b/src/ImageSharp/Formats/Png/PngImageFormatDetector.cs similarity index 76% rename from src/ImageSharp/Formats/Png/PngMimeTypeDetector.cs rename to src/ImageSharp/Formats/Png/PngImageFormatDetector.cs index 6b5d43fbdd..6183ef4496 100644 --- a/src/ImageSharp/Formats/Png/PngMimeTypeDetector.cs +++ b/src/ImageSharp/Formats/Png/PngImageFormatDetector.cs @@ -1,4 +1,4 @@ -// +// // Copyright (c) James Jackson-South and contributors. // Licensed under the Apache License, Version 2.0. // @@ -14,23 +14,23 @@ namespace ImageSharp.Formats /// /// Detects png file headers /// - public class PngMimeTypeDetector : IMimeTypeDetector + public class PngImageFormatDetector : IImageFormatDetector { /// public int HeaderSize => 8; /// - public string DetectMimeType(Span header) + public IImageFormat DetectFormat(ReadOnlySpan header) { if (this.IsSupportedFileFormat(header)) { - return "image/png"; + return ImageFormats.Png; } return null; } - private bool IsSupportedFileFormat(Span header) + private bool IsSupportedFileFormat(ReadOnlySpan header) { return header.Length >= this.HeaderSize && header[0] == 0x89 && diff --git a/src/ImageSharp/Formats/Png/PngImageFormatProvider.cs b/src/ImageSharp/Formats/Png/PngImageFormatProvider.cs deleted file mode 100644 index abbbaa6d57..0000000000 --- a/src/ImageSharp/Formats/Png/PngImageFormatProvider.cs +++ /dev/null @@ -1,45 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats -{ - using System; - using System.Collections.Generic; - using System.IO; - using System.Text; - using ImageSharp.PixelFormats; - - /// - /// Registers the image encoders, decoders and mime type detectors for the png format. - /// - public class PngImageFormatProvider : IImageFormatProvider - { - /// - public void Configure(IImageFormatHost host) - { - var pngEncoder = new PngEncoder(); - foreach (string mimeType in PngConstants.MimeTypes) - { - host.SetMimeTypeEncoder(mimeType, pngEncoder); - } - - foreach (string ext in PngConstants.FileExtensions) - { - foreach (string mimeType in PngConstants.MimeTypes) - { - host.SetFileExtensionToMimeTypeMapping(ext, mimeType); - } - } - - var pngDecoder = new PngDecoder(); - foreach (string mimeType in PngConstants.MimeTypes) - { - host.SetMimeTypeDecoder(mimeType, pngDecoder); - } - - host.AddMimeTypeDetector(new PngMimeTypeDetector()); - } - } -} diff --git a/src/ImageSharp/IConfigurationModule.cs b/src/ImageSharp/IConfigurationModule.cs new file mode 100644 index 0000000000..d37e0042b5 --- /dev/null +++ b/src/ImageSharp/IConfigurationModule.cs @@ -0,0 +1,23 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp +{ + using System; + using System.Collections.Generic; + using System.Text; + + /// + /// Represents an interface that can register image encoders, decoders and image format detectors. + /// + public interface IConfigurationModule + { + /// + /// Called when loaded into a configuration object so the module can register items into the configuration. + /// + /// The configuration that will retain the encoders, decodes and mime type detectors. + void Configure(Configuration configuration); + } +} diff --git a/src/ImageSharp/Image/Image.Decode.cs b/src/ImageSharp/Image/Image.Decode.cs index 436cde466d..2408ec3aa2 100644 --- a/src/ImageSharp/Image/Image.Decode.cs +++ b/src/ImageSharp/Image/Image.Decode.cs @@ -9,7 +9,7 @@ namespace ImageSharp using System.IO; using System.Linq; using Formats; - + using ImageSharp.Memory; using ImageSharp.PixelFormats; /// @@ -23,7 +23,7 @@ namespace ImageSharp /// The image stream to read the header from. /// The configuration. /// The mime type or null if none found. - private static string InternalDiscoverMimeType(Stream stream, Configuration config) + private static IImageFormat InternalDetectFormat(Stream stream, Configuration config) { // This is probably a candidate for making into a public API in the future! int maxHeaderSize = config.MaxHeaderSize; @@ -32,17 +32,12 @@ namespace ImageSharp return null; } - byte[] header = ArrayPool.Shared.Rent(maxHeaderSize); - try + using (var buffer = new Buffer(maxHeaderSize)) { long startPosition = stream.Position; - stream.Read(header, 0, maxHeaderSize); + stream.Read(buffer.Array, 0, maxHeaderSize); stream.Position = startPosition; - return config.MimeTypeDetectors.Select(x => x.DetectMimeType(header)).LastOrDefault(x => x != null); - } - finally - { - ArrayPool.Shared.Return(header); + return config.FormatDetectors.Select(x => x.DetectFormat(buffer)).LastOrDefault(x => x != null); } } @@ -51,14 +46,14 @@ namespace ImageSharp /// /// The image stream to read the header from. /// The configuration. - /// The mimeType. + /// The IImageFormat. /// The image format or null if none found. - private static IImageDecoder DiscoverDecoder(Stream stream, Configuration config, out string mimeType) + private static IImageDecoder DiscoverDecoder(Stream stream, Configuration config, out IImageFormat format) { - mimeType = InternalDiscoverMimeType(stream, config); - if (mimeType != null) + format = InternalDetectFormat(stream, config); + if (format != null) { - return config.FindMimeTypeDecoder(mimeType); + return config.FindDecoder(format); } return null; @@ -74,18 +69,18 @@ namespace ImageSharp /// /// A new . /// - private static (Image img, string mimeType) Decode(Stream stream, Configuration config) + private static (Image img, IImageFormat format) Decode(Stream stream, Configuration config) #pragma warning restore SA1008 // Opening parenthesis must be spaced correctly where TPixel : struct, IPixel { - IImageDecoder decoder = DiscoverDecoder(stream, config, out string mimeType); + IImageDecoder decoder = DiscoverDecoder(stream, config, out IImageFormat format); if (decoder == null) { return (null, null); } Image img = decoder.Decode(config, stream); - return (img, mimeType); + return (img, format); } } } \ No newline at end of file diff --git a/src/ImageSharp/Image/Image.FromBytes.cs b/src/ImageSharp/Image/Image.FromBytes.cs index 3b95211023..c7023b860b 100644 --- a/src/ImageSharp/Image/Image.FromBytes.cs +++ b/src/ImageSharp/Image/Image.FromBytes.cs @@ -16,26 +16,26 @@ namespace ImageSharp public static partial class Image { /// - /// By reading the header on the provided byte array this calculates the images mime type. + /// By reading the header on the provided byte array this calculates the images format. /// /// The byte array containing image data to read the header from. - /// The mime type or null if none found. - public static string DiscoverMimeType(byte[] data) + /// The format or null if none found. + public static IImageFormat DetectFormat(byte[] data) { - return DiscoverMimeType(null, data); + return DetectFormat(null, data); } /// - /// By reading the header on the provided byte array this calculates the images mime type. + /// By reading the header on the provided byte array this calculates the images format. /// /// The configuration. /// The byte array containing image data to read the header from. /// The mime type or null if none found. - public static string DiscoverMimeType(Configuration config, byte[] data) + public static IImageFormat DetectFormat(Configuration config, byte[] data) { using (Stream stream = new MemoryStream(data)) { - return DiscoverMimeType(config, stream); + return DetectFormat(config, stream); } } @@ -50,9 +50,9 @@ namespace ImageSharp /// Create a new instance of the class from the given byte array. /// /// The byte array containing image data. - /// The mime type of the decoded image. + /// The mime type of the decoded image. /// A new . - public static Image Load(byte[] data, out string mimeType) => Load(null, data, out mimeType); + public static Image Load(byte[] data, out IImageFormat format) => Load(null, data, out format); /// /// Create a new instance of the class from the given byte array. @@ -67,9 +67,9 @@ namespace ImageSharp /// /// The config for the decoder. /// The byte array containing image data. - /// The mime type of the decoded image. + /// The mime type of the decoded image. /// A new . - public static Image Load(Configuration config, byte[] data, out string mimeType) => Load(config, data, out mimeType); + public static Image Load(Configuration config, byte[] data, out IImageFormat format) => Load(config, data, out format); /// /// Create a new instance of the class from the given byte array. @@ -104,13 +104,13 @@ namespace ImageSharp /// Create a new instance of the class from the given byte array. /// /// The byte array containing image data. - /// The mime type of the decoded image. + /// The mime type of the decoded image. /// The pixel format. /// A new . - public static Image Load(byte[] data, out string mimeType) + public static Image Load(byte[] data, out IImageFormat format) where TPixel : struct, IPixel { - return Load(null, data, out mimeType); + return Load(null, data, out format); } /// @@ -134,15 +134,15 @@ namespace ImageSharp /// /// The configuration options. /// The byte array containing image data. - /// The mime type of the decoded image. + /// The mime type of the decoded image. /// The pixel format. /// A new . - public static Image Load(Configuration config, byte[] data, out string mimeType) + public static Image Load(Configuration config, byte[] data, out IImageFormat format) where TPixel : struct, IPixel { using (var memoryStream = new MemoryStream(data)) { - return Load(config, memoryStream, out mimeType); + return Load(config, memoryStream, out format); } } diff --git a/src/ImageSharp/Image/Image.FromFile.cs b/src/ImageSharp/Image/Image.FromFile.cs index c44a5da5e6..ca395ce088 100644 --- a/src/ImageSharp/Image/Image.FromFile.cs +++ b/src/ImageSharp/Image/Image.FromFile.cs @@ -21,9 +21,9 @@ namespace ImageSharp /// /// The image file to open and to read the header from. /// The mime type or null if none found. - public static string DiscoverMimeType(string filePath) + public static IImageFormat DetectFormat(string filePath) { - return DiscoverMimeType(null, filePath); + return DetectFormat(null, filePath); } /// @@ -32,12 +32,12 @@ namespace ImageSharp /// The configuration. /// The image file to open and to read the header from. /// The mime type or null if none found. - public static string DiscoverMimeType(Configuration config, string filePath) + public static IImageFormat DetectFormat(Configuration config, string filePath) { config = config ?? Configuration.Default; using (Stream file = config.FileSystem.OpenRead(filePath)) { - return DiscoverMimeType(config, file); + return DetectFormat(config, file); } } @@ -55,12 +55,12 @@ namespace ImageSharp /// Create a new instance of the class from the given file. /// /// The file path to the image. - /// The mime type of the decoded image. + /// The mime type of the decoded image. /// /// Thrown if the stream is not readable nor seekable. /// /// A new . - public static Image Load(string path, out string mimeType) => Load(path, out mimeType); + public static Image Load(string path, out IImageFormat format) => Load(path, out format); /// /// Create a new instance of the class from the given file. @@ -78,12 +78,12 @@ namespace ImageSharp /// /// The config for the decoder. /// The file path to the image. - /// The mime type of the decoded image. + /// The mime type of the decoded image. /// /// Thrown if the stream is not readable nor seekable. /// /// A new . - public static Image Load(Configuration config, string path, out string mimeType) => Load(config, path, out mimeType); + public static Image Load(Configuration config, string path, out IImageFormat format) => Load(config, path, out format); /// /// Create a new instance of the class from the given file. @@ -127,16 +127,16 @@ namespace ImageSharp /// Create a new instance of the class from the given file. /// /// The file path to the image. - /// The mime type of the decoded image. + /// The mime type of the decoded image. /// /// Thrown if the stream is not readable nor seekable. /// /// The pixel format. /// A new . - public static Image Load(string path, out string mimeType) + public static Image Load(string path, out IImageFormat format) where TPixel : struct, IPixel { - return Load(null, path, out mimeType); + return Load(null, path, out format); } /// @@ -164,19 +164,19 @@ namespace ImageSharp /// /// The configuration options. /// The file path to the image. - /// The mime type of the decoded image. + /// The mime type of the decoded image. /// /// Thrown if the stream is not readable nor seekable. /// /// The pixel format. /// A new . - public static Image Load(Configuration config, string path, out string mimeType) + public static Image Load(Configuration config, string path, out IImageFormat format) where TPixel : struct, IPixel { config = config ?? Configuration.Default; using (Stream stream = config.FileSystem.OpenRead(path)) { - return Load(config, stream, out mimeType); + return Load(config, stream, out format); } } diff --git a/src/ImageSharp/Image/Image.FromStream.cs b/src/ImageSharp/Image/Image.FromStream.cs index 19f9304931..7493d66fcc 100644 --- a/src/ImageSharp/Image/Image.FromStream.cs +++ b/src/ImageSharp/Image/Image.FromStream.cs @@ -24,9 +24,9 @@ namespace ImageSharp /// /// The image stream to read the header from. /// The mime type or null if none found. - public static string DiscoverMimeType(Stream stream) + public static IImageFormat DetectFormat(Stream stream) { - return DiscoverMimeType(null, stream); + return DetectFormat(null, stream); } /// @@ -35,21 +35,21 @@ namespace ImageSharp /// The configuration. /// The image stream to read the header from. /// The mime type or null if none found. - public static string DiscoverMimeType(Configuration config, Stream stream) + public static IImageFormat DetectFormat(Configuration config, Stream stream) { - return WithSeekableStream(stream, s => InternalDiscoverMimeType(s, config ?? Configuration.Default)); + return WithSeekableStream(stream, s => InternalDetectFormat(s, config ?? Configuration.Default)); } /// /// Create a new instance of the class from the given stream. /// /// The stream containing image information. - /// the mime type of the decoded image. + /// the mime type of the decoded image. /// /// Thrown if the stream is not readable nor seekable. /// /// A new .> - public static Image Load(Stream stream, out string mimeType) => Load(stream, out mimeType); + public static Image Load(Stream stream, out IImageFormat format) => Load(stream, out format); /// /// Create a new instance of the class from the given stream. @@ -88,12 +88,12 @@ namespace ImageSharp /// /// The config for the decoder. /// The stream containing image information. - /// the mime type of the decoded image. + /// the mime type of the decoded image. /// /// Thrown if the stream is not readable nor seekable. /// /// A new .> - public static Image Load(Configuration config, Stream stream, out string mimeType) => Load(config, stream, out mimeType); + public static Image Load(Configuration config, Stream stream, out IImageFormat format) => Load(config, stream, out format); /// /// Create a new instance of the class from the given stream. @@ -114,16 +114,16 @@ namespace ImageSharp /// Create a new instance of the class from the given stream. /// /// The stream containing image information. - /// the mime type of the decoded image. + /// the mime type of the decoded image. /// /// Thrown if the stream is not readable nor seekable. /// /// The pixel format. /// A new .> - public static Image Load(Stream stream, out string mimeType) + public static Image Load(Stream stream, out IImageFormat format) where TPixel : struct, IPixel { - return Load(null, stream, out mimeType); + return Load(null, stream, out format); } /// @@ -180,20 +180,20 @@ namespace ImageSharp /// /// The configuration options. /// The stream containing image information. - /// the mime type of the decoded image. + /// the mime type of the decoded image. /// /// Thrown if the stream is not readable nor seekable. /// /// The pixel format. /// A new .> - public static Image Load(Configuration config, Stream stream, out string mimeType) + public static Image Load(Configuration config, Stream stream, out IImageFormat format) where TPixel : struct, IPixel { config = config ?? Configuration.Default; - mimeType = null; - (Image img, string mimeType) data = WithSeekableStream(stream, s => Decode(s, config)); + format = null; + (Image img, IImageFormat format) data = WithSeekableStream(stream, s => Decode(s, config)); - mimeType = data.mimeType; + format = data.format; if (data.img != null) { @@ -203,9 +203,9 @@ namespace ImageSharp var stringBuilder = new StringBuilder(); stringBuilder.AppendLine("Image cannot be loaded. Available decoders:"); - foreach (KeyValuePair val in config.ImageDecoders) + foreach (KeyValuePair val in config.ImageDecoders) { - stringBuilder.AppendLine($" - {val.Key} : {val.Value.GetType().Name}"); + stringBuilder.AppendLine($" - {val.Key.Name} : {val.Value.GetType().Name}"); } throw new NotSupportedException(stringBuilder.ToString()); diff --git a/src/ImageSharp/Image/Image{TPixel}.cs b/src/ImageSharp/Image/Image{TPixel}.cs index 5165bc857c..11fea5145b 100644 --- a/src/ImageSharp/Image/Image{TPixel}.cs +++ b/src/ImageSharp/Image/Image{TPixel}.cs @@ -152,22 +152,22 @@ namespace ImageSharp /// Saves the image to the given stream using the currently loaded image format. /// /// The stream to save the image to. - /// The mime type to save the image to. + /// The format to save the image to. /// Thrown if the stream is null. /// The - public Image Save(Stream stream, string mimeType) + public Image Save(Stream stream, IImageFormat format) { - Guard.NotNullOrEmpty(mimeType, nameof(mimeType)); - IImageEncoder encoder = this.Configuration.FindMimeTypeEncoder(mimeType); + Guard.NotNull(format, nameof(format)); + IImageEncoder encoder = this.Configuration.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 this.Configuration.ImageEncoders) + foreach (KeyValuePair val in this.Configuration.ImageEncoders) { - stringBuilder.AppendLine($" - {val.Key} : {val.Value.GetType().Name}"); + stringBuilder.AppendLine($" - {val.Key.Name} : {val.Value.GetType().Name}"); } throw new NotSupportedException(stringBuilder.ToString()); @@ -207,26 +207,28 @@ namespace ImageSharp Guard.NotNullOrEmpty(filePath, nameof(filePath)); string ext = Path.GetExtension(filePath).Trim('.'); - IImageEncoder encoder = this.Configuration.FindFileExtensionsEncoder(ext); - if (encoder == null) + var format = this.Configuration.FindFormatByFileExtensions(ext); + if (format == null) { var stringBuilder = new StringBuilder(); - string mime = this.Configuration.FindFileExtensionsMimeType(ext); - if (mime == null) + stringBuilder.AppendLine($"Can't find a format that is associated with the file extention '{ext}'. Registered formats with there extensions include:"); + foreach (IImageFormat fmt in this.Configuration.ImageFormats) { - stringBuilder.AppendLine($"Can't find a mime type for the file extention '{ext}'. Registered file extension maps include:"); - foreach (KeyValuePair map in this.Configuration.ImageExtensionToMimeTypeMapping) - { - stringBuilder.AppendLine($" - {map.Key} : {map.Value}"); - } + stringBuilder.AppendLine($" - {fmt.Name} : {string.Join(", ", fmt.FileExtensions)}"); } - else + + throw new NotSupportedException(stringBuilder.ToString()); + } + + IImageEncoder encoder = this.Configuration.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 this.Configuration.ImageEncoders) { - stringBuilder.AppendLine($"Can't find encoder for file extention '{ext}' using mime type '{mime}'. Registered encoders include:"); - foreach (KeyValuePair enc in this.Configuration.ImageEncoders) - { - stringBuilder.AppendLine($" - {enc.Key} : {enc.Value.GetType().Name}"); - } + stringBuilder.AppendLine($" - {enc.Key} : {enc.Value.GetType().Name}"); } throw new NotSupportedException(stringBuilder.ToString()); @@ -262,15 +264,15 @@ namespace ImageSharp /// Returns a Base64 encoded string from the given image. /// /// - /// The mimeType. + /// The format. /// The - public string ToBase64String(string mimeType) + public string ToBase64String(IImageFormat format) { using (var stream = new MemoryStream()) { - this.Save(stream, mimeType); + this.Save(stream, format); stream.Flush(); - return $"data:{mimeType};base64,{Convert.ToBase64String(stream.ToArray())}"; + return $"data:{format.DefaultMimeType};base64,{Convert.ToBase64String(stream.ToArray())}"; } } diff --git a/src/ImageSharp/ImageFormats.cs b/src/ImageSharp/ImageFormats.cs new file mode 100644 index 0000000000..fb67fb7146 --- /dev/null +++ b/src/ImageSharp/ImageFormats.cs @@ -0,0 +1,39 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp +{ + using System; + using System.Collections.Generic; + using System.IO; + using ImageSharp.Formats; + using ImageSharp.PixelFormats; + + /// + /// The static collection of all the default image formats + /// + public static class ImageFormats + { + /// + /// The format details for the jpegs. + /// + public static readonly IImageFormat Jpeg = new JpegFormat(); + + /// + /// The format details for the pngs. + /// + public static readonly IImageFormat Png = new PngFormat(); + + /// + /// The format details for the gifs. + /// + public static readonly IImageFormat Gif = new GifFormat(); + + /// + /// The format details for the bitmaps. + /// + public static readonly IImageFormat Bitmap = new BmpFormat(); + } +} diff --git a/src/ImageSharp/Memory/Buffer.cs b/src/ImageSharp/Memory/Buffer.cs index a894ea53a4..4b3681c744 100644 --- a/src/ImageSharp/Memory/Buffer.cs +++ b/src/ImageSharp/Memory/Buffer.cs @@ -115,6 +115,16 @@ namespace ImageSharp.Memory } } + /// + /// Converts to an . + /// + /// The to convert. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator ReadOnlySpan(Buffer buffer) + { + return new ReadOnlySpan(buffer.Array, 0, buffer.Length); + } + /// /// Converts to an . /// diff --git a/tests/ImageSharp.Tests/ConfigurationTests.cs b/tests/ImageSharp.Tests/ConfigurationTests.cs index aa09cf8166..417588180a 100644 --- a/tests/ImageSharp.Tests/ConfigurationTests.cs +++ b/tests/ImageSharp.Tests/ConfigurationTests.cs @@ -40,8 +40,8 @@ namespace ImageSharp.Tests [Fact] public void IfAutoloadWellknwonFormatesIsTrueAllFormateAreLoaded() { - Assert.Equal(6, DefaultConfiguration.ImageEncoders.Count()); - Assert.Equal(6, DefaultConfiguration.ImageDecoders.Count()); + Assert.Equal(4, DefaultConfiguration.ImageEncoders.Count()); + Assert.Equal(4, DefaultConfiguration.ImageDecoders.Count()); } /// @@ -73,11 +73,11 @@ namespace ImageSharp.Tests } [Fact] - public void AddMimeTypeDetectorNullthrows() + public void AddImageFormatDetectorNullthrows() { Assert.Throws(() => { - DefaultConfiguration.AddMimeTypeDetector(null); + DefaultConfiguration.AddImageFormatDetector(null); }); } @@ -86,49 +86,32 @@ namespace ImageSharp.Tests { Assert.Throws(() => { - DefaultConfiguration.SetMimeTypeEncoder(null, new Mock().Object); + DefaultConfiguration.SetEncoder(null, new Mock().Object); }); Assert.Throws(() => { - DefaultConfiguration.SetMimeTypeEncoder("sdsdsd", null); + DefaultConfiguration.SetEncoder(ImageFormats.Bitmap, null); }); Assert.Throws(() => { - DefaultConfiguration.SetMimeTypeEncoder(null, null); + DefaultConfiguration.SetEncoder(null, null); }); } [Fact] - public void RegisterNullFileExtEncoder() + public void RegisterNullSetDecoder() { Assert.Throws(() => { - DefaultConfiguration.SetFileExtensionToMimeTypeMapping(null, "str"); + DefaultConfiguration.SetDecoder(null, new Mock().Object); }); Assert.Throws(() => { - DefaultConfiguration.SetFileExtensionToMimeTypeMapping("sdsdsd", null); + DefaultConfiguration.SetDecoder(ImageFormats.Bitmap, null); }); Assert.Throws(() => { - DefaultConfiguration.SetFileExtensionToMimeTypeMapping(null, null); - }); - } - - [Fact] - public void RegisterNullMimeTypeDecoder() - { - Assert.Throws(() => - { - DefaultConfiguration.SetMimeTypeDecoder(null, new Mock().Object); - }); - Assert.Throws(() => - { - DefaultConfiguration.SetMimeTypeDecoder("sdsdsd", null); - }); - Assert.Throws(() => - { - DefaultConfiguration.SetMimeTypeDecoder(null, null); + DefaultConfiguration.SetDecoder(null, null); }); } @@ -136,28 +119,13 @@ namespace ImageSharp.Tests public void RegisterMimeTypeEncoderReplacesLast() { var encoder1 = new Mock().Object; - ConfigurationEmpty.SetMimeTypeEncoder("test", encoder1); - var found = ConfigurationEmpty.FindMimeTypeEncoder("TEST"); + ConfigurationEmpty.SetEncoder(TestFormat.GlobalTestFormat, encoder1); + var found = ConfigurationEmpty.FindEncoder(TestFormat.GlobalTestFormat); Assert.Equal(encoder1, found); var encoder2 = new Mock().Object; - ConfigurationEmpty.SetMimeTypeEncoder("TEST", encoder2); - var found2 = ConfigurationEmpty.FindMimeTypeEncoder("test"); - Assert.Equal(encoder2, found2); - Assert.NotEqual(found, found2); - } - - [Fact] - public void RegisterFileExtEnecoderReplacesLast() - { - var encoder1 = "mime1"; - ConfigurationEmpty.SetFileExtensionToMimeTypeMapping("TEST", encoder1); - var found = ConfigurationEmpty.FindFileExtensionsMimeType("test"); - Assert.Equal(encoder1, found); - - var encoder2 = "mime2"; - ConfigurationEmpty.SetFileExtensionToMimeTypeMapping("test", encoder2); - var found2 = ConfigurationEmpty.FindFileExtensionsMimeType("TEST"); + ConfigurationEmpty.SetEncoder(TestFormat.GlobalTestFormat, encoder2); + var found2 = ConfigurationEmpty.FindEncoder(TestFormat.GlobalTestFormat); Assert.Equal(encoder2, found2); Assert.NotEqual(found, found2); } @@ -166,13 +134,13 @@ namespace ImageSharp.Tests public void RegisterMimeTypeDecoderReplacesLast() { var decoder1 = new Mock().Object; - ConfigurationEmpty.SetMimeTypeDecoder("test", decoder1); - var found = ConfigurationEmpty.FindMimeTypeDecoder("TEST"); + ConfigurationEmpty.SetDecoder(TestFormat.GlobalTestFormat, decoder1); + var found = ConfigurationEmpty.FindDecoder(TestFormat.GlobalTestFormat); Assert.Equal(decoder1, found); var decoder2 = new Mock().Object; - ConfigurationEmpty.SetMimeTypeDecoder("TEST", decoder2); - var found2 = ConfigurationEmpty.FindMimeTypeDecoder("test"); + ConfigurationEmpty.SetDecoder(TestFormat.GlobalTestFormat, decoder2); + var found2 = ConfigurationEmpty.FindDecoder(TestFormat.GlobalTestFormat); Assert.Equal(decoder2, found2); Assert.NotEqual(found, found2); } @@ -181,7 +149,7 @@ namespace ImageSharp.Tests [Fact] public void ConstructorCallConfigureOnFormatProvider() { - var provider = new Mock(); + var provider = new Mock(); var config = new Configuration(provider.Object); provider.Verify(x => x.Configure(config)); @@ -190,9 +158,9 @@ namespace ImageSharp.Tests [Fact] public void AddFormatCallsConfig() { - var provider = new Mock(); + var provider = new Mock(); var config = new Configuration(); - config.AddImageFormat(provider.Object); + config.Configure(provider.Object); provider.Verify(x => x.Configure(config)); } diff --git a/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs b/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs index 659aa317b8..4ef8fe0612 100644 --- a/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs +++ b/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs @@ -6,7 +6,7 @@ namespace ImageSharp.Tests { using System.IO; - + using ImageSharp.Formats; using ImageSharp.PixelFormats; using Xunit; @@ -36,7 +36,7 @@ namespace ImageSharp.Tests using (Image image = file.CreateImage()) { string filename = path + "/" + file.FileNameWithoutExtension + ".txt"; - File.WriteAllText(filename, image.ToBase64String("image/png")); + File.WriteAllText(filename, image.ToBase64String(ImageFormats.Png)); } } } @@ -135,7 +135,7 @@ namespace ImageSharp.Tests foreach (TestFile file in Files) { byte[] serialized; - using (Image image = Image.Load(file.Bytes, out string mimeType)) + using (Image image = Image.Load(file.Bytes, out IImageFormat mimeType)) using (MemoryStream memoryStream = new MemoryStream()) { image.Save(memoryStream, mimeType); diff --git a/tests/ImageSharp.Tests/Image/ImageDiscoverMimeType.cs b/tests/ImageSharp.Tests/Image/ImageDiscoverMimeType.cs index 80414662b6..59a39c4542 100644 --- a/tests/ImageSharp.Tests/Image/ImageDiscoverMimeType.cs +++ b/tests/ImageSharp.Tests/Image/ImageDiscoverMimeType.cs @@ -17,23 +17,27 @@ namespace ImageSharp.Tests /// /// Tests the class. /// - public class DiscoverMimeTypeTests + public class DiscoverImageFormatTests { private readonly Mock fileSystem; private readonly string FilePath; - private readonly Mock localMimeTypeDetector; + private readonly Mock localMimeTypeDetector; + private readonly Mock localImageFormatMock; + public IImageFormat localImageFormat => localImageFormatMock.Object; public Configuration LocalConfiguration { get; private set; } public byte[] Marker { get; private set; } public MemoryStream DataStream { get; private set; } public byte[] DecodedData { get; private set; } private const string localMimeType = "image/local"; - public DiscoverMimeTypeTests() + public DiscoverImageFormatTests() { - this.localMimeTypeDetector = new Mock(); + this.localImageFormatMock = new Mock(); + + this.localMimeTypeDetector = new Mock(); this.localMimeTypeDetector.Setup(x => x.HeaderSize).Returns(1); - this.localMimeTypeDetector.Setup(x => x.DetectMimeType(It.IsAny>())).Returns(localMimeType); + this.localMimeTypeDetector.Setup(x => x.DetectFormat(It.IsAny>())).Returns(localImageFormatMock.Object); this.fileSystem = new Mock(); @@ -41,7 +45,7 @@ namespace ImageSharp.Tests { FileSystem = this.fileSystem.Object }; - this.LocalConfiguration.AddMimeTypeDetector(this.localMimeTypeDetector.Object); + this.LocalConfiguration.AddImageFormatDetector(this.localMimeTypeDetector.Object); TestFormat.RegisterGloablTestFormat(); this.Marker = Guid.NewGuid().ToByteArray(); @@ -55,52 +59,52 @@ namespace ImageSharp.Tests } [Fact] - public void DiscoverMimeTypeByteArray() + public void DiscoverImageFormatByteArray() { - var type = Image.DiscoverMimeType(DataStream.ToArray()); - Assert.Equal(TestFormat.GlobalTestFormat.MimeType, type); + var type = Image.DetectFormat(DataStream.ToArray()); + Assert.Equal(TestFormat.GlobalTestFormat, type); } [Fact] - public void DiscoverMimeTypeByteArray_WithConfig() + public void DiscoverImageFormatByteArray_WithConfig() { - var type = Image.DiscoverMimeType(this.LocalConfiguration, DataStream.ToArray()); - Assert.Equal(localMimeType, type); + var type = Image.DetectFormat(this.LocalConfiguration, DataStream.ToArray()); + Assert.Equal(localImageFormat, type); } [Fact] - public void DiscoverMimeTypeFile() + public void DiscoverImageFormatFile() { - var type = Image.DiscoverMimeType(this.FilePath); - Assert.Equal(TestFormat.GlobalTestFormat.MimeType, type); + var type = Image.DetectFormat(this.FilePath); + Assert.Equal(TestFormat.GlobalTestFormat, type); } [Fact] - public void DiscoverMimeTypeFilePath_WithConfig() + public void DiscoverImageFormatFilePath_WithConfig() { - var type = Image.DiscoverMimeType(this.LocalConfiguration, FilePath); - Assert.Equal(localMimeType, type); + var type = Image.DetectFormat(this.LocalConfiguration, FilePath); + Assert.Equal(localImageFormat, type); } [Fact] - public void DiscoverMimeTypeStream() + public void DiscoverImageFormatStream() { - var type = Image.DiscoverMimeType(this.DataStream); - Assert.Equal(TestFormat.GlobalTestFormat.MimeType, type); + var type = Image.DetectFormat(this.DataStream); + Assert.Equal(TestFormat.GlobalTestFormat, type); } [Fact] - public void DiscoverMimeTypeFileStream_WithConfig() + public void DiscoverImageFormatFileStream_WithConfig() { - var type = Image.DiscoverMimeType(this.LocalConfiguration, DataStream); - Assert.Equal(localMimeType, type); + var type = Image.DetectFormat(this.LocalConfiguration, DataStream); + Assert.Equal(localImageFormat, type); } [Fact] - public void DiscoverMimeTypeNoDetectorsRegisterdShouldReturnNull() + public void DiscoverImageFormatNoDetectorsRegisterdShouldReturnNull() { - var type = Image.DiscoverMimeType(new Configuration(), DataStream); + var type = Image.DetectFormat(new Configuration(), DataStream); Assert.Null(type); } } diff --git a/tests/ImageSharp.Tests/Image/ImageLoadTests.cs b/tests/ImageSharp.Tests/Image/ImageLoadTests.cs index efd7b69350..bb64ceda34 100644 --- a/tests/ImageSharp.Tests/Image/ImageLoadTests.cs +++ b/tests/ImageSharp.Tests/Image/ImageLoadTests.cs @@ -23,7 +23,8 @@ namespace ImageSharp.Tests private Image returnImage; private Mock localDecoder; private readonly string FilePath; - private readonly Mock localMimeTypeDetector; + private readonly Mock localMimeTypeDetector; + private readonly Mock localImageFormatMock; public Configuration LocalConfiguration { get; private set; } public byte[] Marker { get; private set; } @@ -34,10 +35,12 @@ namespace ImageSharp.Tests { this.returnImage = new Image(1, 1); + this.localImageFormatMock = new Mock(); + this.localDecoder = new Mock(); - this.localMimeTypeDetector = new Mock(); + this.localMimeTypeDetector = new Mock(); this.localMimeTypeDetector.Setup(x => x.HeaderSize).Returns(1); - this.localMimeTypeDetector.Setup(x => x.DetectMimeType(It.IsAny>())).Returns("test"); + this.localMimeTypeDetector.Setup(x => x.DetectFormat(It.IsAny>())).Returns(localImageFormatMock.Object); this.localDecoder.Setup(x => x.Decode(It.IsAny(), It.IsAny())) @@ -56,8 +59,8 @@ namespace ImageSharp.Tests { FileSystem = this.fileSystem.Object }; - this.LocalConfiguration.AddMimeTypeDetector(this.localMimeTypeDetector.Object); - this.LocalConfiguration.SetMimeTypeDecoder("test", this.localDecoder.Object); + this.LocalConfiguration.AddImageFormatDetector(this.localMimeTypeDetector.Object); + this.LocalConfiguration.SetDecoder(localImageFormatMock.Object, this.localDecoder.Object); TestFormat.RegisterGloablTestFormat(); this.Marker = Guid.NewGuid().ToByteArray(); @@ -78,7 +81,6 @@ namespace ImageSharp.Tests Assert.NotNull(img); TestFormat.GlobalTestFormat.VerifyDecodeCall(this.Marker, Configuration.Default); - } [Fact] diff --git a/tests/ImageSharp.Tests/Image/ImageSaveTests.cs b/tests/ImageSharp.Tests/Image/ImageSaveTests.cs index 72461cfc7c..eecb983800 100644 --- a/tests/ImageSharp.Tests/Image/ImageSaveTests.cs +++ b/tests/ImageSharp.Tests/Image/ImageSaveTests.cs @@ -24,13 +24,17 @@ namespace ImageSharp.Tests private readonly Mock fileSystem; private readonly Mock encoder; private readonly Mock encoderNotInFormat; - private Mock localMimeTypeDetector; + private Mock localMimeTypeDetector; + private Mock localImageFormat; public ImageSaveTests() { - this.localMimeTypeDetector = new Mock(); + this.localImageFormat = new Mock(); + this.localImageFormat.Setup(x => x.FileExtensions).Returns(new[] { "png" }); + + this.localMimeTypeDetector = new Mock(); this.localMimeTypeDetector.Setup(x => x.HeaderSize).Returns(1); - this.localMimeTypeDetector.Setup(x => x.DetectMimeType(It.IsAny>())).Returns("img/test"); + this.localMimeTypeDetector.Setup(x => x.DetectFormat(It.IsAny>())).Returns(localImageFormat.Object); this.encoder = new Mock(); @@ -41,9 +45,8 @@ namespace ImageSharp.Tests { FileSystem = this.fileSystem.Object }; - config.AddMimeTypeDetector(this.localMimeTypeDetector.Object); - config.SetMimeTypeEncoder("img/test", this.encoder.Object); - config.SetFileExtensionToMimeTypeMapping("png", "img/test"); + config.AddImageFormatDetector(this.localMimeTypeDetector.Object); + config.SetEncoder(localImageFormat.Object, this.encoder.Object); this.Image = new Image(config, 1, 1); } @@ -72,7 +75,7 @@ namespace ImageSharp.Tests [Fact] public void ToBase64String() { - var str = this.Image.ToBase64String("img/test"); + var str = this.Image.ToBase64String(localImageFormat.Object); this.encoder.Verify(x => x.Encode(this.Image, It.IsAny())); } @@ -81,7 +84,7 @@ namespace ImageSharp.Tests public void SaveStreamWithMime() { Stream stream = new MemoryStream(); - this.Image.Save(stream, "img/test"); + this.Image.Save(stream, localImageFormat.Object); this.encoder.Verify(x => x.Encode(this.Image, stream)); } diff --git a/tests/ImageSharp.Tests/Image/ImageTests.cs b/tests/ImageSharp.Tests/Image/ImageTests.cs index cb8607c091..3157c27d8d 100644 --- a/tests/ImageSharp.Tests/Image/ImageTests.cs +++ b/tests/ImageSharp.Tests/Image/ImageTests.cs @@ -76,7 +76,7 @@ namespace ImageSharp.Tests using (Image img = Image.Load(file, out var mime)) { - Assert.Equal("image/png", mime); + Assert.Equal("image/png", mime.DefaultMimeType); } } @@ -105,7 +105,7 @@ namespace ImageSharp.Tests } using (Image img = Image.Load(file, out var mime)) { - Assert.Equal("image/png", mime); + Assert.Equal("image/png", mime.DefaultMimeType); } } } diff --git a/tests/ImageSharp.Tests/TestFormat.cs b/tests/ImageSharp.Tests/TestFormat.cs index 85e11ee876..5a3cd102e7 100644 --- a/tests/ImageSharp.Tests/TestFormat.cs +++ b/tests/ImageSharp.Tests/TestFormat.cs @@ -19,13 +19,13 @@ namespace ImageSharp.Tests /// /// A test image file. /// - public class TestFormat : IImageFormatProvider + public class TestFormat : IConfigurationModule, IImageFormat { public static TestFormat GlobalTestFormat { get; } = new TestFormat(); public static void RegisterGloablTestFormat() { - Configuration.Default.AddImageFormat(GlobalTestFormat); + Configuration.Default.Configure(GlobalTestFormat); } public TestFormat() @@ -93,7 +93,15 @@ namespace ImageSharp.Tests public int HeaderSize => this.header.Length; - public bool IsSupportedFileFormat(Span header) + public string Name => this.Extension; + + public string DefaultMimeType => this.MimeType; + + public IEnumerable MimeTypes => new[] { this.MimeType }; + + public IEnumerable FileExtensions => this.SupportedExtensions; + + public bool IsSupportedFileFormat(ReadOnlySpan header) { if (header.Length < this.header.Length) { @@ -109,16 +117,11 @@ namespace ImageSharp.Tests return true; } - public void Configure(IImageFormatHost host) + public void Configure(Configuration host) { - host.AddMimeTypeDetector(new TestHeader(this)); - foreach (var ext in this.SupportedExtensions) - { - host.SetFileExtensionToMimeTypeMapping(ext, this.MimeType); - } - - host.SetMimeTypeEncoder(this.MimeType, new TestEncoder(this)); - host.SetMimeTypeDecoder(this.MimeType, new TestDecoder(this)); + host.AddImageFormatDetector(new TestHeader(this)); + host.SetEncoder(this, new TestEncoder(this)); + host.SetDecoder(this, new TestDecoder(this)); } public struct DecodeOperation @@ -150,17 +153,17 @@ namespace ImageSharp.Tests } } - public class TestHeader : IMimeTypeDetector + public class TestHeader : IImageFormatDetector { private TestFormat testFormat; public int HeaderSize => testFormat.HeaderSize; - public string DetectMimeType(Span header) + public IImageFormat DetectFormat(ReadOnlySpan header) { if (testFormat.IsSupportedFileFormat(header)) - return testFormat.MimeType; + return testFormat; return null; } diff --git a/tests/ImageSharp.Tests/TestUtilities/ImagingTestCaseUtility.cs b/tests/ImageSharp.Tests/TestUtilities/ImagingTestCaseUtility.cs index 21b167ca20..47085cf5f4 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ImagingTestCaseUtility.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ImagingTestCaseUtility.cs @@ -124,13 +124,13 @@ namespace ImageSharp.Tests private static IImageEncoder GetImageFormatByExtension(string extension) { extension = extension?.TrimStart('.'); - return Configuration.Default.FindFileExtensionsEncoder(extension); + var format = Configuration.Default.FindFormatByFileExtensions(extension); + return Configuration.Default.FindEncoder(format); } private string GetTestOutputDir() { string testGroupName = Path.GetFileNameWithoutExtension(this.TestGroupName); - return CreateOutputDirectory(testGroupName); } }