mirror of https://github.com/SixLabors/ImageSharp
committed by
GitHub
21 changed files with 504 additions and 395 deletions
@ -1,272 +1,145 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
// Copyright (c) Six Labors and contributors.
|
||||
// Licensed under the Apache License, Version 2.0.
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
using System; |
using System; |
||||
using System.Collections.Concurrent; |
using System.Collections.Concurrent; |
||||
using System.Collections.Generic; |
using System.Collections.Generic; |
||||
using System.Linq; |
using System.Linq; |
||||
using System.Threading.Tasks; |
using System.Threading.Tasks; |
||||
using SixLabors.ImageSharp.Formats; |
using SixLabors.ImageSharp.Formats; |
||||
using SixLabors.ImageSharp.Formats.Bmp; |
using SixLabors.ImageSharp.Formats.Bmp; |
||||
using SixLabors.ImageSharp.Formats.Gif; |
using SixLabors.ImageSharp.Formats.Gif; |
||||
using SixLabors.ImageSharp.Formats.Jpeg; |
using SixLabors.ImageSharp.Formats.Jpeg; |
||||
using SixLabors.ImageSharp.Formats.Png; |
using SixLabors.ImageSharp.Formats.Png; |
||||
using SixLabors.ImageSharp.IO; |
using SixLabors.ImageSharp.IO; |
||||
using SixLabors.ImageSharp.Memory; |
using SixLabors.ImageSharp.Memory; |
||||
|
|
||||
namespace SixLabors.ImageSharp |
namespace SixLabors.ImageSharp |
||||
{ |
{ |
||||
/// <summary>
|
/// <summary>
|
||||
/// Provides initialization code which allows extending the library.
|
/// Provides initialization code which allows extending the library.
|
||||
/// </summary>
|
/// </summary>
|
||||
public sealed class Configuration |
public sealed class Configuration |
||||
{ |
{ |
||||
/// <summary>
|
/// <summary>
|
||||
/// A lazily initialized configuration default instance.
|
/// A lazily initialized configuration default instance.
|
||||
/// </summary>
|
/// </summary>
|
||||
private static readonly Lazy<Configuration> Lazy = new Lazy<Configuration>(CreateDefaultInstance); |
private static readonly Lazy<Configuration> Lazy = new Lazy<Configuration>(CreateDefaultInstance); |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// The list of supported <see cref="IImageEncoder"/> keyed to mime types.
|
/// Initializes a new instance of the <see cref="Configuration" /> class.
|
||||
/// </summary>
|
/// </summary>
|
||||
private readonly ConcurrentDictionary<IImageFormat, IImageEncoder> mimeTypeEncoders = new ConcurrentDictionary<IImageFormat, IImageEncoder>(); |
public Configuration() |
||||
|
{ |
||||
/// <summary>
|
} |
||||
/// The list of supported <see cref="IImageEncoder"/> keyed to mime types.
|
|
||||
/// </summary>
|
/// <summary>
|
||||
private readonly ConcurrentDictionary<IImageFormat, IImageDecoder> mimeTypeDecoders = new ConcurrentDictionary<IImageFormat, IImageDecoder>(); |
/// Initializes a new instance of the <see cref="Configuration" /> class.
|
||||
|
/// </summary>
|
||||
/// <summary>
|
/// <param name="configurationModules">A collection of configuration modules to register</param>
|
||||
/// The list of supported <see cref="IImageFormat"/>s.
|
public Configuration(params IConfigurationModule[] configurationModules) |
||||
/// </summary>
|
{ |
||||
private readonly ConcurrentBag<IImageFormat> imageFormats = new ConcurrentBag<IImageFormat>(); |
if (configurationModules != null) |
||||
|
{ |
||||
/// <summary>
|
foreach (IConfigurationModule p in configurationModules) |
||||
/// The list of supported <see cref="IImageFormatDetector"/>s.
|
{ |
||||
/// </summary>
|
p.Configure(this); |
||||
private ConcurrentBag<IImageFormatDetector> imageFormatDetectors = new ConcurrentBag<IImageFormatDetector>(); |
} |
||||
|
} |
||||
/// <summary>
|
} |
||||
/// Initializes a new instance of the <see cref="Configuration" /> class.
|
|
||||
/// </summary>
|
/// <summary>
|
||||
public Configuration() |
/// Gets the default <see cref="Configuration"/> instance.
|
||||
{ |
/// </summary>
|
||||
} |
public static Configuration Default { get; } = Lazy.Value; |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Configuration" /> class.
|
/// Gets the global parallel options for processing tasks in parallel.
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <param name="configurationModules">A collection of configuration modules to register</param>
|
public ParallelOptions ParallelOptions { get; private set; } = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }; |
||||
public Configuration(params IConfigurationModule[] configurationModules) |
|
||||
{ |
/// <summary>
|
||||
if (configurationModules != null) |
/// Gets the currently registered <see cref="IImageFormat"/>s.
|
||||
{ |
/// </summary>
|
||||
foreach (IConfigurationModule p in configurationModules) |
public IEnumerable<IImageFormat> ImageFormats => this.ImageFormatsManager.ImageFormats; |
||||
{ |
|
||||
p.Configure(this); |
/// <summary>
|
||||
} |
/// Gets or sets the position in a stream to use for reading when using a seekable stream as an image data source.
|
||||
} |
/// </summary>
|
||||
} |
public ReadOrigin ReadOrigin { get; set; } = ReadOrigin.Current; |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets the default <see cref="Configuration"/> instance.
|
/// Gets or sets the <see cref="ImageFormatManager"/> that is currently in use.
|
||||
/// </summary>
|
/// </summary>
|
||||
public static Configuration Default { get; } = Lazy.Value; |
public ImageFormatManager ImageFormatsManager { get; set; } = new ImageFormatManager(); |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets the global parallel options for processing tasks in parallel.
|
/// Gets or sets the <see cref="MemoryManager"/> that is currently in use.
|
||||
/// </summary>
|
/// </summary>
|
||||
public ParallelOptions ParallelOptions { get; } = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }; |
public MemoryManager MemoryManager { get; set; } = ArrayPoolMemoryManager.CreateDefault(); |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Gets the currently registered <see cref="IImageFormat"/>s.
|
/// Gets the maximum header size of all the formats.
|
||||
/// </summary>
|
/// </summary>
|
||||
public IEnumerable<IImageFormat> ImageFormats => this.imageFormats; |
internal int MaxHeaderSize => this.ImageFormatsManager.MaxHeaderSize; |
||||
|
|
||||
/// <summary>
|
#if !NETSTANDARD1_1
|
||||
/// Gets or sets the position in a stream to use for reading when using a seekable stream as an image data source.
|
/// <summary>
|
||||
/// </summary>
|
/// Gets or sets the filesystem helper for accessing the local file system.
|
||||
public ReadOrigin ReadOrigin { get; set; } = ReadOrigin.Current; |
/// </summary>
|
||||
|
internal IFileSystem FileSystem { get; set; } = new LocalFileSystem(); |
||||
/// <summary>
|
#endif
|
||||
/// Gets or sets the <see cref="MemoryManager"/> that is currently in use.
|
|
||||
/// </summary>
|
/// <summary>
|
||||
public MemoryManager MemoryManager { get; set; } = ArrayPoolMemoryManager.CreateDefault(); |
/// Gets or sets the image operations provider factory.
|
||||
|
/// </summary>
|
||||
/// <summary>
|
internal IImageProcessingContextFactory ImageOperationsProvider { get; set; } = new DefaultImageOperationsProviderFactory(); |
||||
/// Gets the maximum header size of all the formats.
|
|
||||
/// </summary>
|
/// <summary>
|
||||
internal int MaxHeaderSize { get; private set; } |
/// Registers a new format provider.
|
||||
|
/// </summary>
|
||||
/// <summary>
|
/// <param name="configuration">The configuration provider to call configure on.</param>
|
||||
/// Gets the currently registered <see cref="IImageFormatDetector"/>s.
|
public void Configure(IConfigurationModule configuration) |
||||
/// </summary>
|
{ |
||||
internal IEnumerable<IImageFormatDetector> FormatDetectors => this.imageFormatDetectors; |
Guard.NotNull(configuration, nameof(configuration)); |
||||
|
configuration.Configure(this); |
||||
/// <summary>
|
} |
||||
/// Gets the currently registered <see cref="IImageDecoder"/>s.
|
|
||||
/// </summary>
|
/// <summary>
|
||||
internal IEnumerable<KeyValuePair<IImageFormat, IImageDecoder>> ImageDecoders => this.mimeTypeDecoders; |
/// Creates a shallow copy of the <see cref="Configuration"/>
|
||||
|
/// </summary>
|
||||
/// <summary>
|
/// <returns>A new configuration instance</returns>
|
||||
/// Gets the currently registered <see cref="IImageEncoder"/>s.
|
public Configuration ShallowCopy() |
||||
/// </summary>
|
{ |
||||
internal IEnumerable<KeyValuePair<IImageFormat, IImageEncoder>> ImageEncoders => this.mimeTypeEncoders; |
return new Configuration |
||||
|
{ |
||||
#if !NETSTANDARD1_1
|
ParallelOptions = this.ParallelOptions, |
||||
/// <summary>
|
ImageFormatsManager = this.ImageFormatsManager, |
||||
/// Gets or sets the filesystem helper for accessing the local file system.
|
MemoryManager = this.MemoryManager, |
||||
/// </summary>
|
ImageOperationsProvider = this.ImageOperationsProvider, |
||||
internal IFileSystem FileSystem { get; set; } = new LocalFileSystem(); |
ReadOrigin = this.ReadOrigin, |
||||
#endif
|
|
||||
|
#if !NETSTANDARD1_1
|
||||
/// <summary>
|
FileSystem = this.FileSystem |
||||
/// Gets or sets the image operations provider factory.
|
#endif
|
||||
/// </summary>
|
}; |
||||
internal IImageProcessingContextFactory ImageOperationsProvider { get; set; } = new DefaultImageOperationsProviderFactory(); |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Registers a new format provider.
|
/// Creates the default instance with the following <see cref="IConfigurationModule"/>s preregistered:
|
||||
/// </summary>
|
/// <para><see cref="PngConfigurationModule"/></para>
|
||||
/// <param name="configuration">The configuration provider to call configure on.</param>
|
/// <para><see cref="JpegConfigurationModule"/></para>
|
||||
public void Configure(IConfigurationModule configuration) |
/// <para><see cref="GifConfigurationModule"/></para>
|
||||
{ |
/// <para><see cref="BmpConfigurationModule"/></para>
|
||||
Guard.NotNull(configuration, nameof(configuration)); |
/// </summary>
|
||||
configuration.Configure(this); |
/// <returns>The default configuration of <see cref="Configuration"/></returns>
|
||||
} |
internal static Configuration CreateDefaultInstance() |
||||
|
{ |
||||
/// <summary>
|
return new Configuration( |
||||
/// Registers a new format provider.
|
new PngConfigurationModule(), |
||||
/// </summary>
|
new JpegConfigurationModule(), |
||||
/// <param name="format">The format to register as a known format.</param>
|
new GifConfigurationModule(), |
||||
public void AddImageFormat(IImageFormat format) |
new BmpConfigurationModule()); |
||||
{ |
} |
||||
Guard.NotNull(format, nameof(format)); |
} |
||||
Guard.NotNull(format.MimeTypes, nameof(format.MimeTypes)); |
} |
||||
Guard.NotNull(format.FileExtensions, nameof(format.FileExtensions)); |
|
||||
this.imageFormats.Add(format); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// For the specified file extensions type find the e <see cref="IImageFormat"/>.
|
|
||||
/// </summary>
|
|
||||
/// <param name="extension">The extension to discover</param>
|
|
||||
/// <returns>The <see cref="IImageFormat"/> if found otherwise null</returns>
|
|
||||
public IImageFormat FindFormatByFileExtension(string extension) |
|
||||
{ |
|
||||
return this.imageFormats.FirstOrDefault(x => x.FileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase)); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// For the specified mime type find the <see cref="IImageFormat"/>.
|
|
||||
/// </summary>
|
|
||||
/// <param name="mimeType">The mime-type to discover</param>
|
|
||||
/// <returns>The <see cref="IImageFormat"/> if found; otherwise null</returns>
|
|
||||
public IImageFormat FindFormatByMimeType(string mimeType) |
|
||||
{ |
|
||||
return this.imageFormats.FirstOrDefault(x => x.MimeTypes.Contains(mimeType, StringComparer.OrdinalIgnoreCase)); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Sets a specific image encoder as the encoder for a specific image format.
|
|
||||
/// </summary>
|
|
||||
/// <param name="imageFormat">The image format to register the encoder for.</param>
|
|
||||
/// <param name="encoder">The encoder to use,</param>
|
|
||||
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); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Sets a specific image decoder as the decoder for a specific image format.
|
|
||||
/// </summary>
|
|
||||
/// <param name="imageFormat">The image format to register the encoder for.</param>
|
|
||||
/// <param name="decoder">The decoder to use,</param>
|
|
||||
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); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Removes all the registered image format detectors.
|
|
||||
/// </summary>
|
|
||||
public void ClearImageFormatDetectors() |
|
||||
{ |
|
||||
this.imageFormatDetectors = new ConcurrentBag<IImageFormatDetector>(); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Adds a new detector for detecting mime types.
|
|
||||
/// </summary>
|
|
||||
/// <param name="detector">The detector to add</param>
|
|
||||
public void AddImageFormatDetector(IImageFormatDetector detector) |
|
||||
{ |
|
||||
Guard.NotNull(detector, nameof(detector)); |
|
||||
this.imageFormatDetectors.Add(detector); |
|
||||
this.SetMaxHeaderSize(); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// For the specified mime type find the decoder.
|
|
||||
/// </summary>
|
|
||||
/// <param name="format">The format to discover</param>
|
|
||||
/// <returns>The <see cref="IImageDecoder"/> if found otherwise null</returns>
|
|
||||
public IImageDecoder FindDecoder(IImageFormat format) |
|
||||
{ |
|
||||
Guard.NotNull(format, nameof(format)); |
|
||||
if (this.mimeTypeDecoders.TryGetValue(format, out IImageDecoder decoder)) |
|
||||
{ |
|
||||
return decoder; |
|
||||
} |
|
||||
|
|
||||
return null; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// For the specified mime type find the encoder.
|
|
||||
/// </summary>
|
|
||||
/// <param name="format">The format to discover</param>
|
|
||||
/// <returns>The <see cref="IImageEncoder"/> if found otherwise null</returns>
|
|
||||
public IImageEncoder FindEncoder(IImageFormat format) |
|
||||
{ |
|
||||
Guard.NotNull(format, nameof(format)); |
|
||||
if (this.mimeTypeEncoders.TryGetValue(format, out IImageEncoder encoder)) |
|
||||
{ |
|
||||
return encoder; |
|
||||
} |
|
||||
|
|
||||
return null; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Creates the default instance with the following <see cref="IConfigurationModule"/>s preregistered:
|
|
||||
/// <para><see cref="PngConfigurationModule"/></para>
|
|
||||
/// <para><see cref="JpegConfigurationModule"/></para>
|
|
||||
/// <para><see cref="GifConfigurationModule"/></para>
|
|
||||
/// <para><see cref="BmpConfigurationModule"/></para>
|
|
||||
/// </summary>
|
|
||||
/// <returns>The default configuration of <see cref="Configuration"/></returns>
|
|
||||
internal static Configuration CreateDefaultInstance() |
|
||||
{ |
|
||||
return new Configuration( |
|
||||
new PngConfigurationModule(), |
|
||||
new JpegConfigurationModule(), |
|
||||
new GifConfigurationModule(), |
|
||||
new BmpConfigurationModule()); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Sets the max header size.
|
|
||||
/// </summary>
|
|
||||
private void SetMaxHeaderSize() |
|
||||
{ |
|
||||
this.MaxHeaderSize = this.imageFormatDetectors.Max(x => x.HeaderSize); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -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 |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Collection of Image Formats to be used in <see cref="Configuration" /> class.
|
||||
|
/// </summary>
|
||||
|
public class ImageFormatManager |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// The list of supported <see cref="IImageEncoder"/> keyed to mime types.
|
||||
|
/// </summary>
|
||||
|
private readonly ConcurrentDictionary<IImageFormat, IImageEncoder> mimeTypeEncoders = new ConcurrentDictionary<IImageFormat, IImageEncoder>(); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// The list of supported <see cref="IImageEncoder"/> keyed to mime types.
|
||||
|
/// </summary>
|
||||
|
private readonly ConcurrentDictionary<IImageFormat, IImageDecoder> mimeTypeDecoders = new ConcurrentDictionary<IImageFormat, IImageDecoder>(); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// The list of supported <see cref="IImageFormat"/>s.
|
||||
|
/// </summary>
|
||||
|
private readonly ConcurrentBag<IImageFormat> imageFormats = new ConcurrentBag<IImageFormat>(); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// The list of supported <see cref="IImageFormatDetector"/>s.
|
||||
|
/// </summary>
|
||||
|
private ConcurrentBag<IImageFormatDetector> imageFormatDetectors = new ConcurrentBag<IImageFormatDetector>(); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="ImageFormatManager" /> class.
|
||||
|
/// </summary>
|
||||
|
public ImageFormatManager() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the maximum header size of all the formats.
|
||||
|
/// </summary>
|
||||
|
internal int MaxHeaderSize { get; private set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the currently registered <see cref="IImageFormat"/>s.
|
||||
|
/// </summary>
|
||||
|
public IEnumerable<IImageFormat> ImageFormats => this.imageFormats; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the currently registered <see cref="IImageFormatDetector"/>s.
|
||||
|
/// </summary>
|
||||
|
internal IEnumerable<IImageFormatDetector> FormatDetectors => this.imageFormatDetectors; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the currently registered <see cref="IImageDecoder"/>s.
|
||||
|
/// </summary>
|
||||
|
internal IEnumerable<KeyValuePair<IImageFormat, IImageDecoder>> ImageDecoders => this.mimeTypeDecoders; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the currently registered <see cref="IImageEncoder"/>s.
|
||||
|
/// </summary>
|
||||
|
internal IEnumerable<KeyValuePair<IImageFormat, IImageEncoder>> ImageEncoders => this.mimeTypeEncoders; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Registers a new format provider.
|
||||
|
/// </summary>
|
||||
|
/// <param name="format">The format to register as a known format.</param>
|
||||
|
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); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// For the specified file extensions type find the e <see cref="IImageFormat"/>.
|
||||
|
/// </summary>
|
||||
|
/// <param name="extension">The extension to discover</param>
|
||||
|
/// <returns>The <see cref="IImageFormat"/> if found otherwise null</returns>
|
||||
|
public IImageFormat FindFormatByFileExtension(string extension) |
||||
|
{ |
||||
|
return this.imageFormats.FirstOrDefault(x => x.FileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase)); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// For the specified mime type find the <see cref="IImageFormat"/>.
|
||||
|
/// </summary>
|
||||
|
/// <param name="mimeType">The mime-type to discover</param>
|
||||
|
/// <returns>The <see cref="IImageFormat"/> if found; otherwise null</returns>
|
||||
|
public IImageFormat FindFormatByMimeType(string mimeType) |
||||
|
{ |
||||
|
return this.imageFormats.FirstOrDefault(x => x.MimeTypes.Contains(mimeType, StringComparer.OrdinalIgnoreCase)); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Sets a specific image encoder as the encoder for a specific image format.
|
||||
|
/// </summary>
|
||||
|
/// <param name="imageFormat">The image format to register the encoder for.</param>
|
||||
|
/// <param name="encoder">The encoder to use,</param>
|
||||
|
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); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Sets a specific image decoder as the decoder for a specific image format.
|
||||
|
/// </summary>
|
||||
|
/// <param name="imageFormat">The image format to register the encoder for.</param>
|
||||
|
/// <param name="decoder">The decoder to use,</param>
|
||||
|
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); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Removes all the registered image format detectors.
|
||||
|
/// </summary>
|
||||
|
public void ClearImageFormatDetectors() |
||||
|
{ |
||||
|
this.imageFormatDetectors = new ConcurrentBag<IImageFormatDetector>(); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Adds a new detector for detecting mime types.
|
||||
|
/// </summary>
|
||||
|
/// <param name="detector">The detector to add</param>
|
||||
|
public void AddImageFormatDetector(IImageFormatDetector detector) |
||||
|
{ |
||||
|
Guard.NotNull(detector, nameof(detector)); |
||||
|
this.imageFormatDetectors.Add(detector); |
||||
|
this.SetMaxHeaderSize(); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// For the specified mime type find the decoder.
|
||||
|
/// </summary>
|
||||
|
/// <param name="format">The format to discover</param>
|
||||
|
/// <returns>The <see cref="IImageDecoder"/> if found otherwise null</returns>
|
||||
|
public IImageDecoder FindDecoder(IImageFormat format) |
||||
|
{ |
||||
|
Guard.NotNull(format, nameof(format)); |
||||
|
if (this.mimeTypeDecoders.TryGetValue(format, out IImageDecoder decoder)) |
||||
|
{ |
||||
|
return decoder; |
||||
|
} |
||||
|
|
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// For the specified mime type find the encoder.
|
||||
|
/// </summary>
|
||||
|
/// <param name="format">The format to discover</param>
|
||||
|
/// <returns>The <see cref="IImageEncoder"/> if found otherwise null</returns>
|
||||
|
public IImageEncoder FindEncoder(IImageFormat format) |
||||
|
{ |
||||
|
Guard.NotNull(format, nameof(format)); |
||||
|
if (this.mimeTypeEncoders.TryGetValue(format, out IImageEncoder encoder)) |
||||
|
{ |
||||
|
return encoder; |
||||
|
} |
||||
|
|
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Sets the max header size.
|
||||
|
/// </summary>
|
||||
|
private void SetMaxHeaderSize() |
||||
|
{ |
||||
|
this.MaxHeaderSize = this.imageFormatDetectors.Max(x => x.HeaderSize); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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<PngEncoder>().Count()); |
||||
|
Assert.Equal(1, this.DefaultFormatsManager.ImageEncoders.Select(item => item.Value).OfType<BmpEncoder>().Count()); |
||||
|
Assert.Equal(1, this.DefaultFormatsManager.ImageEncoders.Select(item => item.Value).OfType<JpegEncoder>().Count()); |
||||
|
Assert.Equal(1, this.DefaultFormatsManager.ImageEncoders.Select(item => item.Value).OfType<GifEncoder>().Count()); |
||||
|
|
||||
|
Assert.Equal(1, this.DefaultFormatsManager.ImageDecoders.Select(item => item.Value).OfType<PngDecoder>().Count()); |
||||
|
Assert.Equal(1, this.DefaultFormatsManager.ImageDecoders.Select(item => item.Value).OfType<BmpDecoder>().Count()); |
||||
|
Assert.Equal(1, this.DefaultFormatsManager.ImageDecoders.Select(item => item.Value).OfType<JpegDecoder>().Count()); |
||||
|
Assert.Equal(1, this.DefaultFormatsManager.ImageDecoders.Select(item => item.Value).OfType<BmpDecoder>().Count()); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void AddImageFormatDetectorNullthrows() |
||||
|
{ |
||||
|
Assert.Throws<ArgumentNullException>(() => |
||||
|
{ |
||||
|
this.DefaultFormatsManager.AddImageFormatDetector(null); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void RegisterNullMimeTypeEncoder() |
||||
|
{ |
||||
|
Assert.Throws<ArgumentNullException>(() => |
||||
|
{ |
||||
|
this.DefaultFormatsManager.SetEncoder(null, new Mock<IImageEncoder>().Object); |
||||
|
}); |
||||
|
Assert.Throws<ArgumentNullException>(() => |
||||
|
{ |
||||
|
this.DefaultFormatsManager.SetEncoder(ImageFormats.Bmp, null); |
||||
|
}); |
||||
|
Assert.Throws<ArgumentNullException>(() => |
||||
|
{ |
||||
|
this.DefaultFormatsManager.SetEncoder(null, null); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void RegisterNullSetDecoder() |
||||
|
{ |
||||
|
Assert.Throws<ArgumentNullException>(() => |
||||
|
{ |
||||
|
this.DefaultFormatsManager.SetDecoder(null, new Mock<IImageDecoder>().Object); |
||||
|
}); |
||||
|
Assert.Throws<ArgumentNullException>(() => |
||||
|
{ |
||||
|
this.DefaultFormatsManager.SetDecoder(ImageFormats.Bmp, null); |
||||
|
}); |
||||
|
Assert.Throws<ArgumentNullException>(() => |
||||
|
{ |
||||
|
this.DefaultFormatsManager.SetDecoder(null, null); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void RegisterMimeTypeEncoderReplacesLast() |
||||
|
{ |
||||
|
IImageEncoder encoder1 = new Mock<IImageEncoder>().Object; |
||||
|
this.FormatsManagerEmpty.SetEncoder(TestFormat.GlobalTestFormat, encoder1); |
||||
|
IImageEncoder found = this.FormatsManagerEmpty.FindEncoder(TestFormat.GlobalTestFormat); |
||||
|
Assert.Equal(encoder1, found); |
||||
|
|
||||
|
IImageEncoder encoder2 = new Mock<IImageEncoder>().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<IImageDecoder>().Object; |
||||
|
this.FormatsManagerEmpty.SetDecoder(TestFormat.GlobalTestFormat, decoder1); |
||||
|
IImageDecoder found = this.FormatsManagerEmpty.FindDecoder(TestFormat.GlobalTestFormat); |
||||
|
Assert.Equal(decoder1, found); |
||||
|
|
||||
|
IImageDecoder decoder2 = new Mock<IImageDecoder>().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<IConfigurationModule>(); |
||||
|
var config = new Configuration(); |
||||
|
config.Configure(provider.Object); |
||||
|
|
||||
|
provider.Verify(x => x.Configure(config)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue