diff --git a/src/ImageSharp/Advanced/AdvancedImageExtensions.cs b/src/ImageSharp/Advanced/AdvancedImageExtensions.cs index 612ced5d8d..24d2dd4cc4 100644 --- a/src/ImageSharp/Advanced/AdvancedImageExtensions.cs +++ b/src/ImageSharp/Advanced/AdvancedImageExtensions.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; +using System.Runtime.InteropServices; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; @@ -148,6 +149,6 @@ namespace SixLabors.ImageSharp.Advanced /// A reference to the element. private static ref TPixel DangerousGetPinnableReferenceToPixelBuffer(IPixelSource source) where TPixel : struct, IPixel - => ref source.PixelBuffer.Span.DangerousGetPinnableReference(); + => ref MemoryMarshal.GetReference(source.PixelBuffer.Span); } } diff --git a/src/ImageSharp/ColorSpaces/CieLab.cs b/src/ImageSharp/ColorSpaces/CieLab.cs index 107be4cb2b..cb08d08bf9 100644 --- a/src/ImageSharp/ColorSpaces/CieLab.cs +++ b/src/ImageSharp/ColorSpaces/CieLab.cs @@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.ColorSpaces /// Represents a CIE L*a*b* 1976 color. /// /// - internal struct CieLab : IColorVector, IEquatable, IAlmostEquatable + internal readonly struct CieLab : IColorVector, IEquatable, IAlmostEquatable { /// /// D50 standard illuminant. diff --git a/src/ImageSharp/ColorSpaces/CieLch.cs b/src/ImageSharp/ColorSpaces/CieLch.cs index 834ef56a89..94443fd863 100644 --- a/src/ImageSharp/ColorSpaces/CieLch.cs +++ b/src/ImageSharp/ColorSpaces/CieLch.cs @@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.ColorSpaces /// Represents the CIE L*C*h°, cylindrical form of the CIE L*a*b* 1976 color. /// /// - internal struct CieLch : IColorVector, IEquatable, IAlmostEquatable + internal readonly struct CieLch : IColorVector, IEquatable, IAlmostEquatable { /// /// D50 standard illuminant. diff --git a/src/ImageSharp/ColorSpaces/CieLchuv.cs b/src/ImageSharp/ColorSpaces/CieLchuv.cs index f35914d641..705b770d35 100644 --- a/src/ImageSharp/ColorSpaces/CieLchuv.cs +++ b/src/ImageSharp/ColorSpaces/CieLchuv.cs @@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.ColorSpaces /// Represents the CIE L*C*h°, cylindrical form of the CIE L*u*v* 1976 color. /// /// - internal struct CieLchuv : IColorVector, IEquatable, IAlmostEquatable + internal readonly struct CieLchuv : IColorVector, IEquatable, IAlmostEquatable { /// /// D50 standard illuminant. diff --git a/src/ImageSharp/ColorSpaces/CieLuv.cs b/src/ImageSharp/ColorSpaces/CieLuv.cs index 9b52517083..b0ae048ab7 100644 --- a/src/ImageSharp/ColorSpaces/CieLuv.cs +++ b/src/ImageSharp/ColorSpaces/CieLuv.cs @@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.ColorSpaces /// attempted perceptual uniformity /// /// - internal struct CieLuv : IColorVector, IEquatable, IAlmostEquatable + internal readonly struct CieLuv : IColorVector, IEquatable, IAlmostEquatable { /// /// D65 standard illuminant. diff --git a/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs b/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs index 487f464d8e..d0a70dd191 100644 --- a/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs +++ b/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs @@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.ColorSpaces /// /// Represents the coordinates of CIEXY chromaticity space /// - internal struct CieXyChromaticityCoordinates : IEquatable, IAlmostEquatable + internal readonly struct CieXyChromaticityCoordinates : IEquatable, IAlmostEquatable { /// /// Represents a that has X, Y values set to zero. diff --git a/src/ImageSharp/ColorSpaces/CieXyy.cs b/src/ImageSharp/ColorSpaces/CieXyy.cs index d5ef4b15d3..751830a0ba 100644 --- a/src/ImageSharp/ColorSpaces/CieXyy.cs +++ b/src/ImageSharp/ColorSpaces/CieXyy.cs @@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.ColorSpaces /// Represents an CIE xyY 1931 color /// /// - internal struct CieXyy : IColorVector, IEquatable, IAlmostEquatable + internal readonly struct CieXyy : IColorVector, IEquatable, IAlmostEquatable { /// /// Represents a that has X, Y, and Y values set to zero. diff --git a/src/ImageSharp/ColorSpaces/CieXyz.cs b/src/ImageSharp/ColorSpaces/CieXyz.cs index 908408000a..0f1866009b 100644 --- a/src/ImageSharp/ColorSpaces/CieXyz.cs +++ b/src/ImageSharp/ColorSpaces/CieXyz.cs @@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.ColorSpaces /// Represents an CIE XYZ 1931 color /// /// - internal struct CieXyz : IColorVector, IEquatable, IAlmostEquatable + internal readonly struct CieXyz : IColorVector, IEquatable, IAlmostEquatable { /// /// Represents a that has X, Y, and Z values set to zero. diff --git a/src/ImageSharp/ColorSpaces/Cmyk.cs b/src/ImageSharp/ColorSpaces/Cmyk.cs index 2a58a5762a..2eb148a8c3 100644 --- a/src/ImageSharp/ColorSpaces/Cmyk.cs +++ b/src/ImageSharp/ColorSpaces/Cmyk.cs @@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.ColorSpaces /// /// Represents an CMYK (cyan, magenta, yellow, keyline) color. /// - internal struct Cmyk : IEquatable, IAlmostEquatable + internal readonly struct Cmyk : IEquatable, IAlmostEquatable { /// /// Represents a that has C, M, Y, and K values set to zero. diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/RgbWorkingSpace.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/RgbWorkingSpace.cs index 19c0ad0ba8..ef86e20901 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/RgbWorkingSpace.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/RgbWorkingSpace.cs @@ -6,7 +6,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation /// /// Trivial implementation of /// - internal struct RgbWorkingSpace : IRgbWorkingSpace + internal readonly struct RgbWorkingSpace : IRgbWorkingSpace { /// /// Initializes a new instance of the struct. diff --git a/src/ImageSharp/ColorSpaces/Hsl.cs b/src/ImageSharp/ColorSpaces/Hsl.cs index cf880f1548..1944ac0c6b 100644 --- a/src/ImageSharp/ColorSpaces/Hsl.cs +++ b/src/ImageSharp/ColorSpaces/Hsl.cs @@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.ColorSpaces /// /// Represents a Hsl (hue, saturation, lightness) color. /// - internal struct Hsl : IColorVector, IEquatable, IAlmostEquatable + internal readonly struct Hsl : IColorVector, IEquatable, IAlmostEquatable { /// /// Represents a that has H, S, and L values set to zero. diff --git a/src/ImageSharp/ColorSpaces/Hsv.cs b/src/ImageSharp/ColorSpaces/Hsv.cs index 9f47393792..45ffd7f121 100644 --- a/src/ImageSharp/ColorSpaces/Hsv.cs +++ b/src/ImageSharp/ColorSpaces/Hsv.cs @@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.ColorSpaces /// /// Represents a HSV (hue, saturation, value) color. Also known as HSB (hue, saturation, brightness). /// - internal struct Hsv : IColorVector, IEquatable, IAlmostEquatable + internal readonly struct Hsv : IColorVector, IEquatable, IAlmostEquatable { /// /// Represents a that has H, S, and V values set to zero. diff --git a/src/ImageSharp/ColorSpaces/HunterLab.cs b/src/ImageSharp/ColorSpaces/HunterLab.cs index b5ba7c86c7..de42518d76 100644 --- a/src/ImageSharp/ColorSpaces/HunterLab.cs +++ b/src/ImageSharp/ColorSpaces/HunterLab.cs @@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.ColorSpaces /// Represents an Hunter LAB color. /// /// - internal struct HunterLab : IColorVector, IEquatable, IAlmostEquatable + internal readonly struct HunterLab : IColorVector, IEquatable, IAlmostEquatable { /// /// D50 standard illuminant. diff --git a/src/ImageSharp/ColorSpaces/LinearRgb.cs b/src/ImageSharp/ColorSpaces/LinearRgb.cs index 07889c3529..b8c446285a 100644 --- a/src/ImageSharp/ColorSpaces/LinearRgb.cs +++ b/src/ImageSharp/ColorSpaces/LinearRgb.cs @@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.ColorSpaces /// /// Represents an linear Rgb color with specified working space /// - internal struct LinearRgb : IColorVector, IEquatable, IAlmostEquatable + internal readonly struct LinearRgb : IColorVector, IEquatable, IAlmostEquatable { /// /// Represents a that has R, G, and B values set to zero. diff --git a/src/ImageSharp/ColorSpaces/Lms.cs b/src/ImageSharp/ColorSpaces/Lms.cs index 40dce5207c..ed0ef64879 100644 --- a/src/ImageSharp/ColorSpaces/Lms.cs +++ b/src/ImageSharp/ColorSpaces/Lms.cs @@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.ColorSpaces /// named after their responsivity (sensitivity) at long, medium and short wavelengths. /// /// - internal struct Lms : IColorVector, IEquatable, IAlmostEquatable + internal readonly struct Lms : IColorVector, IEquatable, IAlmostEquatable { /// /// Represents a that has L, M, and S values set to zero. diff --git a/src/ImageSharp/ColorSpaces/Rgb.cs b/src/ImageSharp/ColorSpaces/Rgb.cs index 8ac8411b20..53fa6086df 100644 --- a/src/ImageSharp/ColorSpaces/Rgb.cs +++ b/src/ImageSharp/ColorSpaces/Rgb.cs @@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.ColorSpaces /// /// Represents an RGB color with specified working space /// - internal struct Rgb : IColorVector, IEquatable, IAlmostEquatable + internal readonly struct Rgb : IColorVector, IEquatable, IAlmostEquatable { /// /// Represents a that has R, G, and B values set to zero. diff --git a/src/ImageSharp/ColorSpaces/YCbCr.cs b/src/ImageSharp/ColorSpaces/YCbCr.cs index 708a74308a..44a0b245d5 100644 --- a/src/ImageSharp/ColorSpaces/YCbCr.cs +++ b/src/ImageSharp/ColorSpaces/YCbCr.cs @@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.ColorSpaces /// /// /// - internal struct YCbCr : IColorVector, IEquatable, IAlmostEquatable + internal readonly struct YCbCr : IColorVector, IEquatable, IAlmostEquatable { /// /// Represents a that has Y, Cb, and Cr values set to zero. diff --git a/src/ImageSharp/Common/Extensions/SimdUtils.cs b/src/ImageSharp/Common/Extensions/SimdUtils.cs index 7f46b7a847..7b77fefcac 100644 --- a/src/ImageSharp/Common/Extensions/SimdUtils.cs +++ b/src/ImageSharp/Common/Extensions/SimdUtils.cs @@ -76,8 +76,8 @@ namespace SixLabors.ImageSharp return; } - ref Vector srcBase = ref Unsafe.As>(ref source.DangerousGetPinnableReference()); - ref Octet.OfByte destBase = ref Unsafe.As(ref dest.DangerousGetPinnableReference()); + ref Vector srcBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(source)); + ref Octet.OfByte destBase = ref Unsafe.As(ref MemoryMarshal.GetReference(dest)); int n = source.Length / 8; Vector magick = new Vector(32768.0f); @@ -117,8 +117,8 @@ namespace SixLabors.ImageSharp return; } - ref Vector srcBase = ref Unsafe.As>(ref source.DangerousGetPinnableReference()); - ref Octet.OfByte destBase = ref Unsafe.As(ref dest.DangerousGetPinnableReference()); + ref Vector srcBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(source)); + ref Octet.OfByte destBase = ref Unsafe.As(ref MemoryMarshal.GetReference(dest)); int n = source.Length / 8; Vector magick = new Vector(32768.0f); diff --git a/src/ImageSharp/Configuration.cs b/src/ImageSharp/Configuration.cs index 34bbb61e0b..d41e48678b 100644 --- a/src/ImageSharp/Configuration.cs +++ b/src/ImageSharp/Configuration.cs @@ -1,272 +1,145 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using SixLabors.ImageSharp.Formats; -using SixLabors.ImageSharp.Formats.Bmp; -using SixLabors.ImageSharp.Formats.Gif; -using SixLabors.ImageSharp.Formats.Jpeg; -using SixLabors.ImageSharp.Formats.Png; -using SixLabors.ImageSharp.IO; -using SixLabors.ImageSharp.Memory; - -namespace SixLabors.ImageSharp -{ - /// - /// Provides initialization code which allows extending the library. - /// - public sealed class Configuration - { - /// - /// A lazily initialized configuration default instance. - /// - private static readonly Lazy Lazy = new Lazy(CreateDefaultInstance); - - /// - /// The list of supported keyed to mime types. - /// - private readonly ConcurrentDictionary mimeTypeEncoders = new ConcurrentDictionary(); - - /// - /// The list of supported keyed to mime types. - /// - private readonly ConcurrentDictionary mimeTypeDecoders = new ConcurrentDictionary(); - - /// - /// The list of supported s. - /// - private readonly ConcurrentBag imageFormats = new ConcurrentBag(); - - /// - /// The list of supported s. - /// - private ConcurrentBag imageFormatDetectors = new ConcurrentBag(); - - /// - /// Initializes a new instance of the class. - /// - public Configuration() - { - } - - /// - /// Initializes a new instance of the class. - /// - /// A collection of configuration modules to register - public Configuration(params IConfigurationModule[] configurationModules) - { - if (configurationModules != null) - { - foreach (IConfigurationModule p in configurationModules) - { - p.Configure(this); - } - } - } - - /// - /// Gets the default instance. - /// - public static Configuration Default { get; } = Lazy.Value; - - /// - /// Gets the global parallel options for processing tasks in parallel. - /// - public ParallelOptions ParallelOptions { get; } = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }; - - /// - /// Gets the currently registered s. - /// - public IEnumerable ImageFormats => this.imageFormats; - - /// - /// Gets or sets the position in a stream to use for reading when using a seekable stream as an image data source. - /// - public ReadOrigin ReadOrigin { get; set; } = ReadOrigin.Current; - - /// - /// Gets or sets the that is currently in use. - /// - public MemoryManager MemoryManager { get; set; } = ArrayPoolMemoryManager.CreateDefault(); - - /// - /// Gets the maximum header size of all the formats. - /// - internal int MaxHeaderSize { get; private set; } - - /// - /// Gets the currently registered s. - /// - internal IEnumerable FormatDetectors => this.imageFormatDetectors; - - /// - /// Gets the currently registered s. - /// - internal IEnumerable> ImageDecoders => this.mimeTypeDecoders; - - /// - /// Gets the currently registered s. - /// - internal IEnumerable> ImageEncoders => this.mimeTypeEncoders; - -#if !NETSTANDARD1_1 - /// - /// Gets or sets the filesystem helper for accessing the local file system. - /// - internal IFileSystem FileSystem { get; set; } = new LocalFileSystem(); -#endif - - /// - /// Gets or sets the image operations provider factory. - /// - internal IImageProcessingContextFactory ImageOperationsProvider { get; set; } = new DefaultImageOperationsProviderFactory(); - - /// - /// Registers a new format provider. - /// - /// The configuration provider to call configure on. - public void Configure(IConfigurationModule configuration) - { - Guard.NotNull(configuration, nameof(configuration)); - configuration.Configure(this); - } - - /// - /// Registers a new format provider. - /// - /// The format to register as a known format. - public void AddImageFormat(IImageFormat format) - { - Guard.NotNull(format, nameof(format)); - Guard.NotNull(format.MimeTypes, nameof(format.MimeTypes)); - Guard.NotNull(format.FileExtensions, nameof(format.FileExtensions)); - this.imageFormats.Add(format); - } - - /// - /// For the specified file extensions type find the e . - /// - /// The extension to discover - /// The if found otherwise null - public IImageFormat FindFormatByFileExtension(string extension) - { - return this.imageFormats.FirstOrDefault(x => x.FileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase)); - } - - /// - /// For the specified mime type find the . - /// - /// The mime-type to discover - /// The if found; otherwise null - public IImageFormat FindFormatByMimeType(string mimeType) - { - return this.imageFormats.FirstOrDefault(x => x.MimeTypes.Contains(mimeType, StringComparer.OrdinalIgnoreCase)); - } - - /// - /// Sets a specific image encoder as the encoder for a specific image format. - /// - /// The image format to register the encoder for. - /// The encoder to use, - public void SetEncoder(IImageFormat imageFormat, IImageEncoder encoder) - { - Guard.NotNull(imageFormat, nameof(imageFormat)); - Guard.NotNull(encoder, nameof(encoder)); - this.AddImageFormat(imageFormat); - this.mimeTypeEncoders.AddOrUpdate(imageFormat, encoder, (s, e) => encoder); - } - - /// - /// Sets a specific image decoder as the decoder for a specific image format. - /// - /// The image format to register the encoder for. - /// The decoder to use, - public void SetDecoder(IImageFormat imageFormat, IImageDecoder decoder) - { - Guard.NotNull(imageFormat, nameof(imageFormat)); - Guard.NotNull(decoder, nameof(decoder)); - this.AddImageFormat(imageFormat); - this.mimeTypeDecoders.AddOrUpdate(imageFormat, decoder, (s, e) => decoder); - } - - /// - /// Removes all the registered image format detectors. - /// - public void ClearImageFormatDetectors() - { - this.imageFormatDetectors = new ConcurrentBag(); - } - - /// - /// Adds a new detector for detecting mime types. - /// - /// The detector to add - public void AddImageFormatDetector(IImageFormatDetector detector) - { - Guard.NotNull(detector, nameof(detector)); - this.imageFormatDetectors.Add(detector); - this.SetMaxHeaderSize(); - } - - /// - /// For the specified mime type find the decoder. - /// - /// The format to discover - /// The if found otherwise null - public IImageDecoder FindDecoder(IImageFormat format) - { - Guard.NotNull(format, nameof(format)); - if (this.mimeTypeDecoders.TryGetValue(format, out IImageDecoder decoder)) - { - return decoder; - } - - return null; - } - - /// - /// For the specified mime type find the encoder. - /// - /// The format to discover - /// The if found otherwise null - public IImageEncoder FindEncoder(IImageFormat format) - { - Guard.NotNull(format, nameof(format)); - if (this.mimeTypeEncoders.TryGetValue(format, out IImageEncoder encoder)) - { - return encoder; - } - - return null; - } - - /// - /// Creates the default instance with the following s preregistered: - /// - /// - /// - /// - /// - /// The default configuration of - internal static Configuration CreateDefaultInstance() - { - return new Configuration( - new PngConfigurationModule(), - new JpegConfigurationModule(), - new GifConfigurationModule(), - new BmpConfigurationModule()); - } - - /// - /// Sets the max header size. - /// - private void SetMaxHeaderSize() - { - this.MaxHeaderSize = this.imageFormatDetectors.Max(x => x.HeaderSize); - } - } -} +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using SixLabors.ImageSharp.Formats; +using SixLabors.ImageSharp.Formats.Bmp; +using SixLabors.ImageSharp.Formats.Gif; +using SixLabors.ImageSharp.Formats.Jpeg; +using SixLabors.ImageSharp.Formats.Png; +using SixLabors.ImageSharp.IO; +using SixLabors.ImageSharp.Memory; + +namespace SixLabors.ImageSharp +{ + /// + /// Provides initialization code which allows extending the library. + /// + public sealed class Configuration + { + /// + /// A lazily initialized configuration default instance. + /// + private static readonly Lazy Lazy = new Lazy(CreateDefaultInstance); + + /// + /// Initializes a new instance of the class. + /// + public Configuration() + { + } + + /// + /// Initializes a new instance of the class. + /// + /// A collection of configuration modules to register + public Configuration(params IConfigurationModule[] configurationModules) + { + if (configurationModules != null) + { + foreach (IConfigurationModule p in configurationModules) + { + p.Configure(this); + } + } + } + + /// + /// Gets the default instance. + /// + public static Configuration Default { get; } = Lazy.Value; + + /// + /// Gets the global parallel options for processing tasks in parallel. + /// + public ParallelOptions ParallelOptions { get; private set; } = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }; + + /// + /// Gets the currently registered s. + /// + public IEnumerable ImageFormats => this.ImageFormatsManager.ImageFormats; + + /// + /// Gets or sets the position in a stream to use for reading when using a seekable stream as an image data source. + /// + public ReadOrigin ReadOrigin { get; set; } = ReadOrigin.Current; + + /// + /// Gets or sets the that is currently in use. + /// + public ImageFormatManager ImageFormatsManager { get; set; } = new ImageFormatManager(); + + /// + /// Gets or sets the that is currently in use. + /// + public MemoryManager MemoryManager { get; set; } = ArrayPoolMemoryManager.CreateDefault(); + + /// + /// Gets the maximum header size of all the formats. + /// + internal int MaxHeaderSize => this.ImageFormatsManager.MaxHeaderSize; + +#if !NETSTANDARD1_1 + /// + /// Gets or sets the filesystem helper for accessing the local file system. + /// + internal IFileSystem FileSystem { get; set; } = new LocalFileSystem(); +#endif + + /// + /// Gets or sets the image operations provider factory. + /// + internal IImageProcessingContextFactory ImageOperationsProvider { get; set; } = new DefaultImageOperationsProviderFactory(); + + /// + /// Registers a new format provider. + /// + /// The configuration provider to call configure on. + public void Configure(IConfigurationModule configuration) + { + Guard.NotNull(configuration, nameof(configuration)); + configuration.Configure(this); + } + + /// + /// Creates a shallow copy of the + /// + /// A new configuration instance + public Configuration ShallowCopy() + { + return new Configuration + { + ParallelOptions = this.ParallelOptions, + ImageFormatsManager = this.ImageFormatsManager, + MemoryManager = this.MemoryManager, + ImageOperationsProvider = this.ImageOperationsProvider, + ReadOrigin = this.ReadOrigin, + +#if !NETSTANDARD1_1 + FileSystem = this.FileSystem +#endif + }; + } + + /// + /// Creates the default instance with the following s preregistered: + /// + /// + /// + /// + /// + /// The default configuration of + internal static Configuration CreateDefaultInstance() + { + return new Configuration( + new PngConfigurationModule(), + new JpegConfigurationModule(), + new GifConfigurationModule(), + new BmpConfigurationModule()); + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Formats/Bmp/BmpConfigurationModule.cs b/src/ImageSharp/Formats/Bmp/BmpConfigurationModule.cs index b091467bf5..956acc1578 100644 --- a/src/ImageSharp/Formats/Bmp/BmpConfigurationModule.cs +++ b/src/ImageSharp/Formats/Bmp/BmpConfigurationModule.cs @@ -11,9 +11,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// public void Configure(Configuration config) { - config.SetEncoder(ImageFormats.Bmp, new BmpEncoder()); - config.SetDecoder(ImageFormats.Bmp, new BmpDecoder()); - config.AddImageFormatDetector(new BmpImageFormatDetector()); + config.ImageFormatsManager.SetEncoder(ImageFormats.Bmp, new BmpEncoder()); + config.ImageFormatsManager.SetDecoder(ImageFormats.Bmp, new BmpDecoder()); + config.ImageFormatsManager.AddImageFormatDetector(new BmpImageFormatDetector()); } } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Bmp/ImageExtensions.cs b/src/ImageSharp/Formats/Bmp/ImageExtensions.cs index 935ce8f4ad..35e168e278 100644 --- a/src/ImageSharp/Formats/Bmp/ImageExtensions.cs +++ b/src/ImageSharp/Formats/Bmp/ImageExtensions.cs @@ -36,6 +36,6 @@ namespace SixLabors.ImageSharp /// Thrown if the stream is null. public static void SaveAsBmp(this Image source, Stream stream, BmpEncoder encoder) where TPixel : struct, IPixel - => source.Save(stream, encoder ?? source.GetConfiguration().FindEncoder(ImageFormats.Bmp)); + => source.Save(stream, encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(ImageFormats.Bmp)); } } diff --git a/src/ImageSharp/Formats/Gif/GifConfigurationModule.cs b/src/ImageSharp/Formats/Gif/GifConfigurationModule.cs index 4c42a833c0..0bb62779eb 100644 --- a/src/ImageSharp/Formats/Gif/GifConfigurationModule.cs +++ b/src/ImageSharp/Formats/Gif/GifConfigurationModule.cs @@ -11,10 +11,10 @@ namespace SixLabors.ImageSharp.Formats.Gif /// public void Configure(Configuration config) { - config.SetEncoder(ImageFormats.Gif, new GifEncoder()); - config.SetDecoder(ImageFormats.Gif, new GifDecoder()); + config.ImageFormatsManager.SetEncoder(ImageFormats.Gif, new GifEncoder()); + config.ImageFormatsManager.SetDecoder(ImageFormats.Gif, new GifDecoder()); - config.AddImageFormatDetector(new GifImageFormatDetector()); + config.ImageFormatsManager.AddImageFormatDetector(new GifImageFormatDetector()); } } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Gif/ImageExtensions.cs b/src/ImageSharp/Formats/Gif/ImageExtensions.cs index 939eb456e1..78acadb4b1 100644 --- a/src/ImageSharp/Formats/Gif/ImageExtensions.cs +++ b/src/ImageSharp/Formats/Gif/ImageExtensions.cs @@ -36,6 +36,6 @@ namespace SixLabors.ImageSharp /// Thrown if the stream is null. public static void SaveAsGif(this Image source, Stream stream, GifEncoder encoder) where TPixel : struct, IPixel - => source.Save(stream, encoder ?? source.GetConfiguration().FindEncoder(ImageFormats.Gif)); + => source.Save(stream, encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(ImageFormats.Gif)); } } diff --git a/src/ImageSharp/Formats/Gif/PackedField.cs b/src/ImageSharp/Formats/Gif/PackedField.cs index 962e2082bf..28a415e2b8 100644 --- a/src/ImageSharp/Formats/Gif/PackedField.cs +++ b/src/ImageSharp/Formats/Gif/PackedField.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.Formats.Gif /// Represents a byte of data in a GIF data stream which contains a number /// of data items. /// - internal struct PackedField : IEquatable + internal readonly struct PackedField : IEquatable { /// /// The individual bits representing the packed byte. diff --git a/src/ImageSharp/Formats/ImageFormatManager.cs b/src/ImageSharp/Formats/ImageFormatManager.cs new file mode 100644 index 0000000000..67ba111474 --- /dev/null +++ b/src/ImageSharp/Formats/ImageFormatManager.cs @@ -0,0 +1,186 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SixLabors.ImageSharp.Formats +{ + /// + /// Collection of Image Formats to be used in class. + /// + public class ImageFormatManager + { + /// + /// The list of supported keyed to mime types. + /// + private readonly ConcurrentDictionary mimeTypeEncoders = new ConcurrentDictionary(); + + /// + /// The list of supported keyed to mime types. + /// + private readonly ConcurrentDictionary mimeTypeDecoders = new ConcurrentDictionary(); + + /// + /// The list of supported s. + /// + private readonly ConcurrentBag imageFormats = new ConcurrentBag(); + + /// + /// The list of supported s. + /// + private ConcurrentBag imageFormatDetectors = new ConcurrentBag(); + + /// + /// Initializes a new instance of the class. + /// + public ImageFormatManager() + { + } + + /// + /// Gets the maximum header size of all the formats. + /// + internal int MaxHeaderSize { get; private set; } + + /// + /// Gets the currently registered s. + /// + public IEnumerable ImageFormats => this.imageFormats; + + /// + /// Gets the currently registered s. + /// + internal IEnumerable FormatDetectors => this.imageFormatDetectors; + + /// + /// Gets the currently registered s. + /// + internal IEnumerable> ImageDecoders => this.mimeTypeDecoders; + + /// + /// Gets the currently registered s. + /// + internal IEnumerable> ImageEncoders => this.mimeTypeEncoders; + + /// + /// Registers a new format provider. + /// + /// The format to register as a known format. + public void AddImageFormat(IImageFormat format) + { + Guard.NotNull(format, nameof(format)); + Guard.NotNull(format.MimeTypes, nameof(format.MimeTypes)); + Guard.NotNull(format.FileExtensions, nameof(format.FileExtensions)); + this.imageFormats.Add(format); + } + + /// + /// For the specified file extensions type find the e . + /// + /// The extension to discover + /// The if found otherwise null + public IImageFormat FindFormatByFileExtension(string extension) + { + return this.imageFormats.FirstOrDefault(x => x.FileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase)); + } + + /// + /// For the specified mime type find the . + /// + /// The mime-type to discover + /// The if found; otherwise null + public IImageFormat FindFormatByMimeType(string mimeType) + { + return this.imageFormats.FirstOrDefault(x => x.MimeTypes.Contains(mimeType, StringComparer.OrdinalIgnoreCase)); + } + + /// + /// Sets a specific image encoder as the encoder for a specific image format. + /// + /// The image format to register the encoder for. + /// The encoder to use, + public void SetEncoder(IImageFormat imageFormat, IImageEncoder encoder) + { + Guard.NotNull(imageFormat, nameof(imageFormat)); + Guard.NotNull(encoder, nameof(encoder)); + this.AddImageFormat(imageFormat); + this.mimeTypeEncoders.AddOrUpdate(imageFormat, encoder, (s, e) => encoder); + } + + /// + /// Sets a specific image decoder as the decoder for a specific image format. + /// + /// The image format to register the encoder for. + /// The decoder to use, + public void SetDecoder(IImageFormat imageFormat, IImageDecoder decoder) + { + Guard.NotNull(imageFormat, nameof(imageFormat)); + Guard.NotNull(decoder, nameof(decoder)); + this.AddImageFormat(imageFormat); + this.mimeTypeDecoders.AddOrUpdate(imageFormat, decoder, (s, e) => decoder); + } + + /// + /// Removes all the registered image format detectors. + /// + public void ClearImageFormatDetectors() + { + this.imageFormatDetectors = new ConcurrentBag(); + } + + /// + /// Adds a new detector for detecting mime types. + /// + /// The detector to add + public void AddImageFormatDetector(IImageFormatDetector detector) + { + Guard.NotNull(detector, nameof(detector)); + this.imageFormatDetectors.Add(detector); + this.SetMaxHeaderSize(); + } + + /// + /// For the specified mime type find the decoder. + /// + /// The format to discover + /// The if found otherwise null + public IImageDecoder FindDecoder(IImageFormat format) + { + Guard.NotNull(format, nameof(format)); + if (this.mimeTypeDecoders.TryGetValue(format, out IImageDecoder decoder)) + { + return decoder; + } + + return null; + } + + /// + /// For the specified mime type find the encoder. + /// + /// The format to discover + /// The if found otherwise null + public IImageEncoder FindEncoder(IImageFormat format) + { + Guard.NotNull(format, nameof(format)); + if (this.mimeTypeEncoders.TryGetValue(format, out IImageEncoder encoder)) + { + return encoder; + } + + return null; + } + + /// + /// Sets the max header size. + /// + private void SetMaxHeaderSize() + { + this.MaxHeaderSize = this.imageFormatDetectors.Max(x => x.HeaderSize); + } + } +} diff --git a/src/ImageSharp/Formats/Jpeg/Common/Block8x8.cs b/src/ImageSharp/Formats/Jpeg/Common/Block8x8.cs index 1066cfa808..11a456ef9b 100644 --- a/src/ImageSharp/Formats/Jpeg/Common/Block8x8.cs +++ b/src/ImageSharp/Formats/Jpeg/Common/Block8x8.cs @@ -4,6 +4,7 @@ using System; using System.Diagnostics; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using System.Text; namespace SixLabors.ImageSharp.Formats.Jpeg.Common @@ -34,7 +35,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common public Block8x8(Span coefficients) { ref byte selfRef = ref Unsafe.As(ref this); - ref byte sourceRef = ref coefficients.NonPortableCast().DangerousGetPinnableReference(); + ref byte sourceRef = ref MemoryMarshal.GetReference(coefficients.NonPortableCast()); Unsafe.CopyBlock(ref selfRef, ref sourceRef, Size * sizeof(short)); } @@ -204,7 +205,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common public void CopyTo(Span destination) { ref byte selfRef = ref Unsafe.As(ref this); - ref byte destRef = ref destination.NonPortableCast().DangerousGetPinnableReference(); + ref byte destRef = ref MemoryMarshal.GetReference(destination.NonPortableCast()); Unsafe.CopyBlock(ref destRef, ref selfRef, Size * sizeof(short)); } diff --git a/src/ImageSharp/Formats/Jpeg/Common/Block8x8F.cs b/src/ImageSharp/Formats/Jpeg/Common/Block8x8F.cs index 2dd42288cb..f45b5df4eb 100644 --- a/src/ImageSharp/Formats/Jpeg/Common/Block8x8F.cs +++ b/src/ImageSharp/Formats/Jpeg/Common/Block8x8F.cs @@ -163,7 +163,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common [MethodImpl(MethodImplOptions.AggressiveInlining)] public void LoadFrom(Span source) { - ref byte s = ref Unsafe.As(ref source.DangerousGetPinnableReference()); + ref byte s = ref Unsafe.As(ref MemoryMarshal.GetReference(source)); ref byte d = ref Unsafe.As(ref this); Unsafe.CopyBlock(ref d, ref s, Size * sizeof(float)); @@ -203,7 +203,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common [MethodImpl(MethodImplOptions.AggressiveInlining)] public void CopyTo(Span dest) { - ref byte d = ref Unsafe.As(ref dest.DangerousGetPinnableReference()); + ref byte d = ref Unsafe.As(ref MemoryMarshal.GetReference(dest)); ref byte s = ref Unsafe.As(ref this); Unsafe.CopyBlock(ref d, ref s, Size * sizeof(float)); diff --git a/src/ImageSharp/Formats/Jpeg/Common/Decoder/AdobeMarker.cs b/src/ImageSharp/Formats/Jpeg/Common/Decoder/AdobeMarker.cs index 0ec2297d76..d55e36bd48 100644 --- a/src/ImageSharp/Formats/Jpeg/Common/Decoder/AdobeMarker.cs +++ b/src/ImageSharp/Formats/Jpeg/Common/Decoder/AdobeMarker.cs @@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder /// Provides information about the Adobe marker segment. /// /// See the included 5116.DCT.pdf file in the source for more information. - internal struct AdobeMarker : IEquatable + internal readonly struct AdobeMarker : IEquatable { /// /// Gets the length of an adobe marker segment. diff --git a/src/ImageSharp/Formats/Jpeg/Common/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimd.cs b/src/ImageSharp/Formats/Jpeg/Common/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimd.cs index a7fc136afe..2f214f88a9 100644 --- a/src/ImageSharp/Formats/Jpeg/Common/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimd.cs +++ b/src/ImageSharp/Formats/Jpeg/Common/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimd.cs @@ -4,6 +4,7 @@ using System; using System.Numerics; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using SixLabors.ImageSharp.Common.Tuples; namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder.ColorConverters @@ -37,14 +38,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder.ColorConverters DebugGuard.IsTrue(result.Length % 8 == 0, nameof(result), "result.Length should be divisable by 8!"); ref Vector4Pair yBase = - ref Unsafe.As(ref values.Component0.DangerousGetPinnableReference()); + ref Unsafe.As(ref MemoryMarshal.GetReference(values.Component0)); ref Vector4Pair cbBase = - ref Unsafe.As(ref values.Component1.DangerousGetPinnableReference()); + ref Unsafe.As(ref MemoryMarshal.GetReference(values.Component1)); ref Vector4Pair crBase = - ref Unsafe.As(ref values.Component2.DangerousGetPinnableReference()); + ref Unsafe.As(ref MemoryMarshal.GetReference(values.Component2)); ref Vector4Octet resultBase = - ref Unsafe.As(ref result.DangerousGetPinnableReference()); + ref Unsafe.As(ref MemoryMarshal.GetReference(result)); var chromaOffset = new Vector4(-128f); diff --git a/src/ImageSharp/Formats/Jpeg/Common/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimdAvx2.cs b/src/ImageSharp/Formats/Jpeg/Common/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimdAvx2.cs index 77e74c32b0..f8a4514221 100644 --- a/src/ImageSharp/Formats/Jpeg/Common/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimdAvx2.cs +++ b/src/ImageSharp/Formats/Jpeg/Common/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimdAvx2.cs @@ -4,6 +4,7 @@ using System; using System.Numerics; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using SixLabors.ImageSharp.Common.Tuples; // ReSharper disable ImpureMethodCallOnReadonlyValueField @@ -46,14 +47,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder.ColorConverters } ref Vector yBase = - ref Unsafe.As>(ref values.Component0.DangerousGetPinnableReference()); + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0)); ref Vector cbBase = - ref Unsafe.As>(ref values.Component1.DangerousGetPinnableReference()); + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1)); ref Vector crBase = - ref Unsafe.As>(ref values.Component2.DangerousGetPinnableReference()); + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2)); ref Vector4Octet resultBase = - ref Unsafe.As(ref result.DangerousGetPinnableReference()); + ref Unsafe.As(ref MemoryMarshal.GetReference(result)); var chromaOffset = new Vector(-128f); diff --git a/src/ImageSharp/Formats/Jpeg/Common/Decoder/ColorConverters/JpegColorConverter.cs b/src/ImageSharp/Formats/Jpeg/Common/Decoder/ColorConverters/JpegColorConverter.cs index e0abc3215c..187b65f72b 100644 --- a/src/ImageSharp/Formats/Jpeg/Common/Decoder/ColorConverters/JpegColorConverter.cs +++ b/src/ImageSharp/Formats/Jpeg/Common/Decoder/ColorConverters/JpegColorConverter.cs @@ -66,7 +66,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder.ColorConverters /// /// A stack-only struct to reference the input buffers using -s. /// - public struct ComponentValues +#pragma warning disable SA1206 // Declaration keywords should follow order + public readonly ref struct ComponentValues +#pragma warning restore SA1206 // Declaration keywords should follow order { /// /// The component count diff --git a/src/ImageSharp/Formats/Jpeg/Common/Decoder/JFifMarker.cs b/src/ImageSharp/Formats/Jpeg/Common/Decoder/JFifMarker.cs index cba7be5539..c856fd04a6 100644 --- a/src/ImageSharp/Formats/Jpeg/Common/Decoder/JFifMarker.cs +++ b/src/ImageSharp/Formats/Jpeg/Common/Decoder/JFifMarker.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder /// Provides information about the JFIF marker segment /// TODO: Thumbnail? /// - internal struct JFifMarker : IEquatable + internal readonly struct JFifMarker : IEquatable { /// /// Gets the length of an JFIF marker segment. diff --git a/src/ImageSharp/Formats/Jpeg/Common/GenericBlock8x8.cs b/src/ImageSharp/Formats/Jpeg/Common/GenericBlock8x8.cs index e20e850d74..09a7eb73aa 100644 --- a/src/ImageSharp/Formats/Jpeg/Common/GenericBlock8x8.cs +++ b/src/ImageSharp/Formats/Jpeg/Common/GenericBlock8x8.cs @@ -85,7 +85,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common ref byte blockStart = ref Unsafe.As, byte>(ref this); ref byte imageStart = ref Unsafe.As( - ref Unsafe.Add(ref source.GetRowSpan(sourceY).DangerousGetPinnableReference(), sourceX)); + ref Unsafe.Add(ref MemoryMarshal.GetReference(source.GetRowSpan(sourceY)), sourceX)); int blockRowSizeInBytes = 8 * Unsafe.SizeOf(); int imageRowSizeInBytes = source.Width * Unsafe.SizeOf(); diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/InputProcessor.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/InputProcessor.cs index 88599808fc..cb4b63cffd 100644 --- a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/InputProcessor.cs +++ b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/InputProcessor.cs @@ -5,8 +5,6 @@ using System; using System.IO; using System.Runtime.CompilerServices; -using SixLabors.ImageSharp.Memory; - namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder { /// @@ -382,5 +380,13 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder this.LastErrorCode = this.Bits.ReceiveExtendUnsafe(t, ref this, out x); return this.LastErrorCode; } + + /// + /// Reset the Huffman decoder. + /// + public void ResetHuffmanDecoder() + { + this.Bits = default(Bits); + } } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigJpegScanDecoder.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigJpegScanDecoder.cs index 67abba9f33..d10def3ce7 100644 --- a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigJpegScanDecoder.cs +++ b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigJpegScanDecoder.cs @@ -94,6 +94,21 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder /// private int eobRun; + /// + /// The block counter + /// + private int blockCounter; + + /// + /// The MCU counter + /// + private int mcuCounter; + + /// + /// The expected RST marker value + /// + private byte expectedRst; + /// /// Initializes a default-constructed instance for reading data from -s stream. /// @@ -139,100 +154,136 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder { decoder.InputProcessor.ResetErrorState(); - int blockCount = 0; - int mcu = 0; - byte expectedRst = OrigJpegConstants.Markers.RST0; + this.blockCounter = 0; + this.mcuCounter = 0; + this.expectedRst = OrigJpegConstants.Markers.RST0; for (int my = 0; my < decoder.MCUCountY; my++) { for (int mx = 0; mx < decoder.MCUCountX; mx++) { - for (int scanIndex = 0; scanIndex < this.componentScanCount; scanIndex++) - { - this.ComponentIndex = this.pointers.ComponentScan[scanIndex].ComponentIndex; - OrigComponent component = decoder.Components[this.ComponentIndex]; + this.DecodeBlocksAtMcuIndex(decoder, mx, my); - this.hi = component.HorizontalSamplingFactor; - int vi = component.VerticalSamplingFactor; - - for (int j = 0; j < this.hi * vi; j++) - { - if (this.componentScanCount != 1) - { - this.bx = (this.hi * mx) + (j % this.hi); - this.by = (vi * my) + (j / this.hi); - } - else - { - int q = decoder.MCUCountX * this.hi; - this.bx = blockCount % q; - this.by = blockCount / q; - blockCount++; - if (this.bx * 8 >= decoder.ImageWidth || this.by * 8 >= decoder.ImageHeight) - { - continue; - } - } + this.mcuCounter++; - // Find the block at (bx,by) in the component's buffer: - ref Block8x8 blockRefOnHeap = ref component.GetBlockReference(this.bx, this.by); + // Handling restart intervals + // Useful info: https://stackoverflow.com/a/8751802 + if (decoder.IsAtRestartInterval(this.mcuCounter)) + { + this.ProcessRSTMarker(decoder); + this.Reset(decoder); + } + } + } + } - // Copy block to stack - this.data.Block = blockRefOnHeap; + private void DecodeBlocksAtMcuIndex(OrigJpegDecoderCore decoder, int mx, int my) + { + for (int scanIndex = 0; scanIndex < this.componentScanCount; scanIndex++) + { + this.ComponentIndex = this.pointers.ComponentScan[scanIndex].ComponentIndex; + OrigComponent component = decoder.Components[this.ComponentIndex]; - if (!decoder.InputProcessor.ReachedEOF) - { - this.DecodeBlock(decoder, scanIndex); - } + this.hi = component.HorizontalSamplingFactor; + int vi = component.VerticalSamplingFactor; - // Store the result block: - blockRefOnHeap = this.data.Block; + for (int j = 0; j < this.hi * vi; j++) + { + if (this.componentScanCount != 1) + { + this.bx = (this.hi * mx) + (j % this.hi); + this.by = (vi * my) + (j / this.hi); + } + else + { + int q = decoder.MCUCountX * this.hi; + this.bx = this.blockCounter % q; + this.by = this.blockCounter / q; + this.blockCounter++; + if (this.bx * 8 >= decoder.ImageWidth || this.by * 8 >= decoder.ImageHeight) + { + continue; } + } + + // Find the block at (bx,by) in the component's buffer: + ref Block8x8 blockRefOnHeap = ref component.GetBlockReference(this.bx, this.by); - // for j + // Copy block to stack + this.data.Block = blockRefOnHeap; + + if (!decoder.InputProcessor.ReachedEOF) + { + this.DecodeBlock(decoder, scanIndex); } - // for i - mcu++; + // Store the result block: + blockRefOnHeap = this.data.Block; + } + } + } - if (decoder.RestartInterval > 0 && mcu % decoder.RestartInterval == 0 && mcu < decoder.TotalMCUCount) + private void ProcessRSTMarker(OrigJpegDecoderCore decoder) + { + // Attempt to look for RST[0-7] markers to resynchronize from corrupt input. + if (!decoder.InputProcessor.ReachedEOF) + { + decoder.InputProcessor.ReadFullUnsafe(decoder.Temp, 0, 2); + if (decoder.InputProcessor.CheckEOFEnsureNoError()) + { + if (decoder.Temp[0] != 0xFF || decoder.Temp[1] != this.expectedRst) { - // A more sophisticated decoder could use RST[0-7] markers to resynchronize from corrupt input, - // but this one assumes well-formed input, and hence the restart marker follows immediately. - if (!decoder.InputProcessor.ReachedEOF) + bool invalidRst = true; + + // Most jpeg's containing well-formed input will have a RST[0-7] marker following immediately + // but some, see Issue #481, contain padding bytes "0xFF" before the RST[0-7] marker. + // If we identify that case we attempt to read until we have bypassed the padded bytes. + // We then check again for our RST marker and throw if invalid. + // No other methods are attempted to resynchronize from corrupt input. + if (decoder.Temp[0] == 0xFF && decoder.Temp[1] == 0xFF) { - decoder.InputProcessor.ReadFullUnsafe(decoder.Temp, 0, 2); - if (decoder.InputProcessor.CheckEOFEnsureNoError()) + while (decoder.Temp[0] == 0xFF && decoder.InputProcessor.CheckEOFEnsureNoError()) { - if (decoder.Temp[0] != 0xff || decoder.Temp[1] != expectedRst) - { - throw new ImageFormatException("Bad RST marker"); - } - - expectedRst++; - if (expectedRst == OrigJpegConstants.Markers.RST7 + 1) + decoder.InputProcessor.ReadFullUnsafe(decoder.Temp, 0, 1); + if (!decoder.InputProcessor.CheckEOFEnsureNoError()) { - expectedRst = OrigJpegConstants.Markers.RST0; + break; } } - } - // Reset the Huffman decoder. - decoder.InputProcessor.Bits = default(Bits); + // Have we found a valid restart marker? + invalidRst = decoder.Temp[0] != this.expectedRst; + } - // Reset the DC components, as per section F.2.1.3.1. - this.ResetDc(); + if (invalidRst) + { + throw new ImageFormatException("Bad RST marker"); + } + } - // Reset the progressive decoder state, as per section G.1.2.2. - this.eobRun = 0; + this.expectedRst++; + if (this.expectedRst == OrigJpegConstants.Markers.RST7 + 1) + { + this.expectedRst = OrigJpegConstants.Markers.RST0; } } - - // for mx } } - private void ResetDc() + private void Reset(OrigJpegDecoderCore decoder) + { + decoder.InputProcessor.ResetHuffmanDecoder(); + + this.ResetDcValues(); + + // Reset the progressive decoder state, as per section G.1.2.2. + this.eobRun = 0; + } + + /// + /// Reset the DC components, as per section F.2.1.3.1. + /// + private void ResetDcValues() { Unsafe.InitBlock(this.pointers.Dc, default(byte), sizeof(int) * OrigJpegDecoderCore.MaxComponents); } diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Encoder/HuffmanLut.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Encoder/HuffmanLut.cs index 2fb01c5c8c..7756a7e3ba 100644 --- a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Encoder/HuffmanLut.cs +++ b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Encoder/HuffmanLut.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Encoder /// codeword size in bits and the 24 least significant bits hold the codeword. /// The maximum codeword size is 16 bits. /// - internal struct HuffmanLut + internal readonly struct HuffmanLut { /// /// The compiled representations of theHuffmanSpec. diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Encoder/HuffmanSpec.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Encoder/HuffmanSpec.cs index 8e40cb3689..1c8228aaa2 100644 --- a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Encoder/HuffmanSpec.cs +++ b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Encoder/HuffmanSpec.cs @@ -6,7 +6,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Encoder /// /// The Huffman encoding specifications. /// - internal struct HuffmanSpec + internal readonly struct HuffmanSpec { #pragma warning disable SA1118 // ParameterMustNotSpanMultipleLines diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs index 58513fd297..6cc275d49d 100644 --- a/src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs @@ -411,6 +411,15 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort this.InitDerivedMetaDataProperties(); } + /// + /// Returns true if 'mcuCounter' is at restart interval + /// + public bool IsAtRestartInterval(int mcuCounter) + { + return this.RestartInterval > 0 && mcuCounter % this.RestartInterval == 0 + && mcuCounter < this.TotalMCUCount; + } + /// /// Assigns derived metadata properties to , eg. horizontal and vertical resolution if it has a JFIF header. /// diff --git a/src/ImageSharp/Formats/Jpeg/ImageExtensions.cs b/src/ImageSharp/Formats/Jpeg/ImageExtensions.cs index 9cd7b3a8bd..d3f95e40c0 100644 --- a/src/ImageSharp/Formats/Jpeg/ImageExtensions.cs +++ b/src/ImageSharp/Formats/Jpeg/ImageExtensions.cs @@ -36,6 +36,6 @@ namespace SixLabors.ImageSharp /// Thrown if the stream is null. public static void SaveAsJpeg(this Image source, Stream stream, JpegEncoder encoder) where TPixel : struct, IPixel - => source.Save(stream, encoder ?? source.GetConfiguration().FindEncoder(ImageFormats.Jpeg)); + => source.Save(stream, encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(ImageFormats.Jpeg)); } } diff --git a/src/ImageSharp/Formats/Jpeg/JpegConfigurationModule.cs b/src/ImageSharp/Formats/Jpeg/JpegConfigurationModule.cs index 1ab5093398..23cef59273 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegConfigurationModule.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegConfigurationModule.cs @@ -11,10 +11,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// public void Configure(Configuration config) { - config.SetEncoder(ImageFormats.Jpeg, new JpegEncoder()); - config.SetDecoder(ImageFormats.Jpeg, new JpegDecoder()); + config.ImageFormatsManager.SetEncoder(ImageFormats.Jpeg, new JpegEncoder()); + config.ImageFormatsManager.SetDecoder(ImageFormats.Jpeg, new JpegDecoder()); - config.AddImageFormatDetector(new JpegImageFormatDetector()); + config.ImageFormatsManager.AddImageFormatDetector(new JpegImageFormatDetector()); } } } diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsScanDecoder.cs b/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsScanDecoder.cs index 9e245ea2c6..c6f6ac270f 100644 --- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsScanDecoder.cs +++ b/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsScanDecoder.cs @@ -154,7 +154,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components ushort marker = fileMarker.Marker; - // RSTn - We've alread read the bytes and altered the position so no need to skip + // RSTn - We've already read the bytes and altered the position so no need to skip if (marker >= PdfJsJpegConstants.Markers.RST0 && marker <= PdfJsJpegConstants.Markers.RST7) { continue; diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsYCbCrToRgbTables.cs b/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsYCbCrToRgbTables.cs index ddc577270b..203a7b1eb2 100644 --- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsYCbCrToRgbTables.cs +++ b/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsYCbCrToRgbTables.cs @@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components /// Provides 8-bit lookup tables for converting from YCbCr to Rgb colorspace. /// Methods to build the tables are based on libjpeg implementation. /// - internal struct PdfJsYCbCrToRgbTables + internal readonly struct PdfJsYCbCrToRgbTables { /// /// The red red-chrominance table diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoderCore.cs index 4fa0bc281d..54e2833b11 100644 --- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoderCore.cs @@ -137,7 +137,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort return new PdfJsFileMarker(PdfJsJpegConstants.Markers.EOI, (int)stream.Length - 2); } - marker[1] = (byte)value; + marker[1] = (byte)suffix; } return new PdfJsFileMarker((ushort)((marker[0] << 8) | marker[1]), (int)(stream.Position - 2)); diff --git a/src/ImageSharp/Formats/Png/Filters/AverageFilter.cs b/src/ImageSharp/Formats/Png/Filters/AverageFilter.cs index 0d3a65dbd8..de62d47029 100644 --- a/src/ImageSharp/Formats/Png/Filters/AverageFilter.cs +++ b/src/ImageSharp/Formats/Png/Filters/AverageFilter.cs @@ -3,6 +3,7 @@ using System; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace SixLabors.ImageSharp.Formats.Png.Filters { @@ -24,8 +25,8 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters { DebugGuard.MustBeSameSized(scanline, previousScanline, nameof(scanline)); - ref byte scanBaseRef = ref scanline.DangerousGetPinnableReference(); - ref byte prevBaseRef = ref previousScanline.DangerousGetPinnableReference(); + ref byte scanBaseRef = ref MemoryMarshal.GetReference(scanline); + ref byte prevBaseRef = ref MemoryMarshal.GetReference(previousScanline); // Average(x) + floor((Raw(x-bpp)+Prior(x))/2) for (int x = 1; x < scanline.Length; x++) @@ -60,9 +61,9 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters DebugGuard.MustBeSameSized(scanline, previousScanline, nameof(scanline)); DebugGuard.MustBeSizedAtLeast(result, scanline, nameof(result)); - ref byte scanBaseRef = ref scanline.DangerousGetPinnableReference(); - ref byte prevBaseRef = ref previousScanline.DangerousGetPinnableReference(); - ref byte resultBaseRef = ref result.DangerousGetPinnableReference(); + ref byte scanBaseRef = ref MemoryMarshal.GetReference(scanline); + ref byte prevBaseRef = ref MemoryMarshal.GetReference(previousScanline); + ref byte resultBaseRef = ref MemoryMarshal.GetReference(result); sum = 0; // Average(x) = Raw(x) - floor((Raw(x-bpp)+Prior(x))/2) diff --git a/src/ImageSharp/Formats/Png/Filters/PaethFilter.cs b/src/ImageSharp/Formats/Png/Filters/PaethFilter.cs index 08e4938804..7e05d736f9 100644 --- a/src/ImageSharp/Formats/Png/Filters/PaethFilter.cs +++ b/src/ImageSharp/Formats/Png/Filters/PaethFilter.cs @@ -3,6 +3,7 @@ using System; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace SixLabors.ImageSharp.Formats.Png.Filters { @@ -25,8 +26,8 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters { DebugGuard.MustBeSameSized(scanline, previousScanline, nameof(scanline)); - ref byte scanBaseRef = ref scanline.DangerousGetPinnableReference(); - ref byte prevBaseRef = ref previousScanline.DangerousGetPinnableReference(); + ref byte scanBaseRef = ref MemoryMarshal.GetReference(scanline); + ref byte prevBaseRef = ref MemoryMarshal.GetReference(previousScanline); // Paeth(x) + PaethPredictor(Raw(x-bpp), Prior(x), Prior(x-bpp)) int offset = bytesPerPixel + 1; @@ -61,9 +62,9 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters DebugGuard.MustBeSameSized(scanline, previousScanline, nameof(scanline)); DebugGuard.MustBeSizedAtLeast(result, scanline, nameof(result)); - ref byte scanBaseRef = ref scanline.DangerousGetPinnableReference(); - ref byte prevBaseRef = ref previousScanline.DangerousGetPinnableReference(); - ref byte resultBaseRef = ref result.DangerousGetPinnableReference(); + ref byte scanBaseRef = ref MemoryMarshal.GetReference(scanline); + ref byte prevBaseRef = ref MemoryMarshal.GetReference(previousScanline); + ref byte resultBaseRef = ref MemoryMarshal.GetReference(result); sum = 0; // Paeth(x) = Raw(x) - PaethPredictor(Raw(x-bpp), Prior(x), Prior(x - bpp)) diff --git a/src/ImageSharp/Formats/Png/Filters/SubFilter.cs b/src/ImageSharp/Formats/Png/Filters/SubFilter.cs index 5ee8664400..c0db7da935 100644 --- a/src/ImageSharp/Formats/Png/Filters/SubFilter.cs +++ b/src/ImageSharp/Formats/Png/Filters/SubFilter.cs @@ -3,6 +3,7 @@ using System; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace SixLabors.ImageSharp.Formats.Png.Filters { @@ -21,7 +22,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Decode(Span scanline, int bytesPerPixel) { - ref byte scanBaseRef = ref scanline.DangerousGetPinnableReference(); + ref byte scanBaseRef = ref MemoryMarshal.GetReference(scanline); // Sub(x) + Raw(x-bpp) for (int x = 1; x < scanline.Length; x++) @@ -52,8 +53,8 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters { DebugGuard.MustBeSizedAtLeast(result, scanline, nameof(result)); - ref byte scanBaseRef = ref scanline.DangerousGetPinnableReference(); - ref byte resultBaseRef = ref result.DangerousGetPinnableReference(); + ref byte scanBaseRef = ref MemoryMarshal.GetReference(scanline); + ref byte resultBaseRef = ref MemoryMarshal.GetReference(result); sum = 0; // Sub(x) = Raw(x) - Raw(x-bpp) diff --git a/src/ImageSharp/Formats/Png/Filters/UpFilter.cs b/src/ImageSharp/Formats/Png/Filters/UpFilter.cs index 6e8f780e5c..81c063ea9e 100644 --- a/src/ImageSharp/Formats/Png/Filters/UpFilter.cs +++ b/src/ImageSharp/Formats/Png/Filters/UpFilter.cs @@ -3,6 +3,7 @@ using System; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace SixLabors.ImageSharp.Formats.Png.Filters { @@ -23,8 +24,8 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters { DebugGuard.MustBeSameSized(scanline, previousScanline, nameof(scanline)); - ref byte scanBaseRef = ref scanline.DangerousGetPinnableReference(); - ref byte prevBaseRef = ref previousScanline.DangerousGetPinnableReference(); + ref byte scanBaseRef = ref MemoryMarshal.GetReference(scanline); + ref byte prevBaseRef = ref MemoryMarshal.GetReference(previousScanline); // Up(x) + Prior(x) for (int x = 1; x < scanline.Length; x++) @@ -48,9 +49,9 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters DebugGuard.MustBeSameSized(scanline, previousScanline, nameof(scanline)); DebugGuard.MustBeSizedAtLeast(result, scanline, nameof(result)); - ref byte scanBaseRef = ref scanline.DangerousGetPinnableReference(); - ref byte prevBaseRef = ref previousScanline.DangerousGetPinnableReference(); - ref byte resultBaseRef = ref result.DangerousGetPinnableReference(); + ref byte scanBaseRef = ref MemoryMarshal.GetReference(scanline); + ref byte prevBaseRef = ref MemoryMarshal.GetReference(previousScanline); + ref byte resultBaseRef = ref MemoryMarshal.GetReference(result); sum = 0; // Up(x) = Raw(x) - Prior(x) diff --git a/src/ImageSharp/Formats/Png/ImageExtensions.cs b/src/ImageSharp/Formats/Png/ImageExtensions.cs index 10970fc16a..f25d2bffe2 100644 --- a/src/ImageSharp/Formats/Png/ImageExtensions.cs +++ b/src/ImageSharp/Formats/Png/ImageExtensions.cs @@ -35,6 +35,6 @@ namespace SixLabors.ImageSharp /// Thrown if the stream is null. public static void SaveAsPng(this Image source, Stream stream, PngEncoder encoder) where TPixel : struct, IPixel - => source.Save(stream, encoder ?? source.GetConfiguration().FindEncoder(ImageFormats.Png)); + => source.Save(stream, encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(ImageFormats.Png)); } } diff --git a/src/ImageSharp/Formats/Png/PngConfigurationModule.cs b/src/ImageSharp/Formats/Png/PngConfigurationModule.cs index ab6f31d49a..0036280a83 100644 --- a/src/ImageSharp/Formats/Png/PngConfigurationModule.cs +++ b/src/ImageSharp/Formats/Png/PngConfigurationModule.cs @@ -11,9 +11,9 @@ namespace SixLabors.ImageSharp.Formats.Png /// public void Configure(Configuration config) { - config.SetEncoder(ImageFormats.Png, new PngEncoder()); - config.SetDecoder(ImageFormats.Png, new PngDecoder()); - config.AddImageFormatDetector(new PngImageFormatDetector()); + config.ImageFormatsManager.SetEncoder(ImageFormats.Png, new PngEncoder()); + config.ImageFormatsManager.SetDecoder(ImageFormats.Png, new PngDecoder()); + config.ImageFormatsManager.AddImageFormatDetector(new PngImageFormatDetector()); } } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs index fbff0ae1d9..c1dccdcafc 100644 --- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs @@ -701,7 +701,7 @@ namespace SixLabors.ImageSharp.Formats.Png Span rowSpan = pixels.GetPixelRowSpan(this.currentRow); // Trim the first marker byte from the buffer - var scanlineBuffer = new Span(defilteredScanline, 1); + var scanlineBuffer = new Span(defilteredScanline, 1, defilteredScanline.Length - 1); switch (this.pngColorType) { @@ -932,7 +932,7 @@ namespace SixLabors.ImageSharp.Formats.Png var color = default(TPixel); // Trim the first marker byte from the buffer - var scanlineBuffer = new Span(defilteredScanline, 1); + var scanlineBuffer = new Span(defilteredScanline, 1, defilteredScanline.Length - 1); switch (this.pngColorType) { diff --git a/src/ImageSharp/Image/Image.Decode.cs b/src/ImageSharp/Image/Image.Decode.cs index 72492a494b..6b44c893bc 100644 --- a/src/ImageSharp/Image/Image.Decode.cs +++ b/src/ImageSharp/Image/Image.Decode.cs @@ -34,7 +34,7 @@ namespace SixLabors.ImageSharp long startPosition = stream.Position; stream.Read(buffer.Array, 0, maxHeaderSize); stream.Position = startPosition; - return config.FormatDetectors.Select(x => x.DetectFormat(buffer.Span)).LastOrDefault(x => x != null); + return config.ImageFormatsManager.FormatDetectors.Select(x => x.DetectFormat(buffer.Span)).LastOrDefault(x => x != null); } } @@ -50,7 +50,7 @@ namespace SixLabors.ImageSharp format = InternalDetectFormat(stream, config); if (format != null) { - return config.FindDecoder(format); + return config.ImageFormatsManager.FindDecoder(format); } return null; diff --git a/src/ImageSharp/Image/Image.FromStream.cs b/src/ImageSharp/Image/Image.FromStream.cs index 4e294260aa..9061c334dc 100644 --- a/src/ImageSharp/Image/Image.FromStream.cs +++ b/src/ImageSharp/Image/Image.FromStream.cs @@ -186,7 +186,7 @@ namespace SixLabors.ImageSharp var stringBuilder = new StringBuilder(); stringBuilder.AppendLine("Image cannot be loaded. Available decoders:"); - foreach (KeyValuePair val in config.ImageDecoders) + foreach (KeyValuePair val in config.ImageFormatsManager.ImageDecoders) { stringBuilder.AppendLine($" - {val.Key.Name} : {val.Value.GetType().Name}"); } diff --git a/src/ImageSharp/Image/ImageExtensions.cs b/src/ImageSharp/Image/ImageExtensions.cs index c4de1c2988..7d23d95d9c 100644 --- a/src/ImageSharp/Image/ImageExtensions.cs +++ b/src/ImageSharp/Image/ImageExtensions.cs @@ -32,7 +32,7 @@ namespace SixLabors.ImageSharp Guard.NotNullOrEmpty(filePath, nameof(filePath)); string ext = Path.GetExtension(filePath).Trim('.'); - IImageFormat format = source.GetConfiguration().FindFormatByFileExtension(ext); + IImageFormat format = source.GetConfiguration().ImageFormatsManager.FindFormatByFileExtension(ext); if (format == null) { var stringBuilder = new StringBuilder(); @@ -45,13 +45,13 @@ namespace SixLabors.ImageSharp throw new NotSupportedException(stringBuilder.ToString()); } - IImageEncoder encoder = source.GetConfiguration().FindEncoder(format); + IImageEncoder encoder = source.GetConfiguration().ImageFormatsManager.FindEncoder(format); if (encoder == null) { var stringBuilder = new StringBuilder(); stringBuilder.AppendLine($"Can't find encoder for file extention '{ext}' using image format '{format.Name}'. Registered encoders include:"); - foreach (KeyValuePair enc in source.GetConfiguration().ImageEncoders) + foreach (KeyValuePair enc in source.GetConfiguration().ImageFormatsManager.ImageEncoders) { stringBuilder.AppendLine($" - {enc.Key} : {enc.Value.GetType().Name}"); } @@ -93,14 +93,14 @@ namespace SixLabors.ImageSharp where TPixel : struct, IPixel { Guard.NotNull(format, nameof(format)); - IImageEncoder encoder = source.GetConfiguration().FindEncoder(format); + IImageEncoder encoder = source.GetConfiguration().ImageFormatsManager.FindEncoder(format); if (encoder == null) { var stringBuilder = new StringBuilder(); stringBuilder.AppendLine("Can't find encoder for provided mime type. Available encoded:"); - foreach (KeyValuePair val in source.GetConfiguration().ImageEncoders) + foreach (KeyValuePair val in source.GetConfiguration().ImageFormatsManager.ImageEncoders) { stringBuilder.AppendLine($" - {val.Key.Name} : {val.Value.GetType().Name}"); } diff --git a/src/ImageSharp/ImageSharp.csproj b/src/ImageSharp/ImageSharp.csproj index cb0539f786..86a0ab7ea5 100644 --- a/src/ImageSharp/ImageSharp.csproj +++ b/src/ImageSharp/ImageSharp.csproj @@ -29,6 +29,7 @@ portable True IOperation + 7.2 @@ -40,12 +41,11 @@ All - - + + - diff --git a/src/ImageSharp/Memory/BufferArea{T}.cs b/src/ImageSharp/Memory/BufferArea{T}.cs index 588eae483d..990b494fc7 100644 --- a/src/ImageSharp/Memory/BufferArea{T}.cs +++ b/src/ImageSharp/Memory/BufferArea{T}.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.Memory /// This type is kind-of 2D Span, but it can live on heap. /// /// The element type - internal struct BufferArea + internal readonly struct BufferArea where T : struct { /// diff --git a/src/ImageSharp/Memory/BufferExtensions.cs b/src/ImageSharp/Memory/BufferExtensions.cs index 919a6ef345..dd3114c21c 100644 --- a/src/ImageSharp/Memory/BufferExtensions.cs +++ b/src/ImageSharp/Memory/BufferExtensions.cs @@ -4,6 +4,7 @@ using System; using System.IO; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace SixLabors.ImageSharp.Memory { @@ -53,7 +54,7 @@ namespace SixLabors.ImageSharp.Memory public static ref T DangerousGetPinnableReference(this IBuffer buffer) where T : struct => - ref buffer.Span.DangerousGetPinnableReference(); + ref MemoryMarshal.GetReference(buffer.Span); public static void Read(this Stream stream, IManagedByteBuffer buffer) { diff --git a/src/ImageSharp/Memory/SpanHelper.cs b/src/ImageSharp/Memory/SpanHelper.cs index 73bc5f55d8..0c327484a0 100644 --- a/src/ImageSharp/Memory/SpanHelper.cs +++ b/src/ImageSharp/Memory/SpanHelper.cs @@ -4,6 +4,7 @@ using System; using System.Numerics; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace SixLabors.ImageSharp.Memory { @@ -22,7 +23,7 @@ namespace SixLabors.ImageSharp.Memory public static ref Vector FetchVector(this Span span) where T : struct { - return ref Unsafe.As>(ref span.DangerousGetPinnableReference()); + return ref Unsafe.As>(ref MemoryMarshal.GetReference(span)); } /// @@ -39,8 +40,8 @@ namespace SixLabors.ImageSharp.Memory DebugGuard.MustBeLessThanOrEqualTo(count, source.Length, nameof(count)); DebugGuard.MustBeLessThanOrEqualTo(count, destination.Length, nameof(count)); - ref byte srcRef = ref Unsafe.As(ref source.DangerousGetPinnableReference()); - ref byte destRef = ref Unsafe.As(ref destination.DangerousGetPinnableReference()); + ref byte srcRef = ref Unsafe.As(ref MemoryMarshal.GetReference(source)); + ref byte destRef = ref Unsafe.As(ref MemoryMarshal.GetReference(destination)); int byteCount = Unsafe.SizeOf() * count; diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccColorantTableEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccColorantTableEntry.cs index 17127110d6..c5b005ea09 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccColorantTableEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccColorantTableEntry.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// /// Entry of ICC colorant table /// - internal struct IccColorantTableEntry : IEquatable + internal readonly struct IccColorantTableEntry : IEquatable { /// /// Initializes a new instance of the struct. diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccNamedColor.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccNamedColor.cs index 98107e8281..22916c1344 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccNamedColor.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccNamedColor.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// /// A specific color with a name /// - internal struct IccNamedColor : IEquatable + internal readonly struct IccNamedColor : IEquatable { /// /// Initializes a new instance of the struct. diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccPositionNumber.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccPositionNumber.cs index 6258ca2f36..d886dc099c 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccPositionNumber.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccPositionNumber.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// /// Position of an object within an ICC profile /// - internal struct IccPositionNumber : IEquatable + internal readonly struct IccPositionNumber : IEquatable { /// /// Initializes a new instance of the struct. diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileId.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileId.cs index 1f96540df3..4070f835d6 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileId.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileId.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// /// ICC Profile ID /// - public struct IccProfileId : IEquatable + public readonly struct IccProfileId : IEquatable { /// /// A profile ID with all values set to zero diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccResponseNumber.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccResponseNumber.cs index a10c55f4e4..c786a0fd45 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccResponseNumber.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccResponseNumber.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// /// Associates a normalized device code with a measurement value /// - internal struct IccResponseNumber : IEquatable + internal readonly struct IccResponseNumber : IEquatable { /// /// Initializes a new instance of the struct. diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccScreeningChannel.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccScreeningChannel.cs index f41858f303..e1f1bb32fe 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccScreeningChannel.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccScreeningChannel.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// /// A single channel of a /// - internal struct IccScreeningChannel : IEquatable + internal readonly struct IccScreeningChannel : IEquatable { /// /// Initializes a new instance of the struct. diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccTagTableEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccTagTableEntry.cs index 5464de9c5f..7cb5c7901e 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccTagTableEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccTagTableEntry.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// /// Entry of ICC tag table /// - internal struct IccTagTableEntry : IEquatable + internal readonly struct IccTagTableEntry : IEquatable { /// /// Initializes a new instance of the struct. diff --git a/src/ImageSharp/Numerics/ValueSize.cs b/src/ImageSharp/Numerics/ValueSize.cs index 659e0ebfe1..fcf61a586d 100644 --- a/src/ImageSharp/Numerics/ValueSize.cs +++ b/src/ImageSharp/Numerics/ValueSize.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp /// /// Represents a value in relation to a value on the image /// - internal struct ValueSize : IEquatable + internal readonly struct ValueSize : IEquatable { /// /// Initializes a new instance of the struct. diff --git a/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.cs b/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.cs index 9553ec82d6..9505ee6cf7 100644 --- a/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.cs +++ b/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.cs @@ -6,7 +6,8 @@ namespace SixLabors.ImageSharp.PixelFormats { using System; using System.Runtime.CompilerServices; - + using System.Runtime.InteropServices; + public partial class PixelOperations { @@ -20,8 +21,8 @@ namespace SixLabors.ImageSharp.PixelFormats { GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); - ref Rgba32 sourceRef = ref source.DangerousGetPinnableReference(); - ref TPixel destRef = ref destPixels.DangerousGetPinnableReference(); + ref Rgba32 sourceRef = ref MemoryMarshal.GetReference(source); + ref TPixel destRef = ref MemoryMarshal.GetReference(destPixels); Rgba32 rgba = new Rgba32(0, 0, 0, 255); @@ -57,8 +58,8 @@ namespace SixLabors.ImageSharp.PixelFormats { GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); - ref TPixel sourceBaseRef = ref sourcePixels.DangerousGetPinnableReference(); - ref Rgba32 destBaseRef = ref dest.DangerousGetPinnableReference(); + ref TPixel sourceBaseRef = ref MemoryMarshal.GetReference(sourcePixels); + ref Rgba32 destBaseRef = ref MemoryMarshal.GetReference(dest); for (int i = 0; i < count; i++) { @@ -91,8 +92,8 @@ namespace SixLabors.ImageSharp.PixelFormats { GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); - ref Bgra32 sourceRef = ref source.DangerousGetPinnableReference(); - ref TPixel destRef = ref destPixels.DangerousGetPinnableReference(); + ref Bgra32 sourceRef = ref MemoryMarshal.GetReference(source); + ref TPixel destRef = ref MemoryMarshal.GetReference(destPixels); Rgba32 rgba = new Rgba32(0, 0, 0, 255); @@ -128,8 +129,8 @@ namespace SixLabors.ImageSharp.PixelFormats { GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); - ref TPixel sourceBaseRef = ref sourcePixels.DangerousGetPinnableReference(); - ref Bgra32 destBaseRef = ref dest.DangerousGetPinnableReference(); + ref TPixel sourceBaseRef = ref MemoryMarshal.GetReference(sourcePixels); + ref Bgra32 destBaseRef = ref MemoryMarshal.GetReference(dest); for (int i = 0; i < count; i++) { @@ -162,8 +163,8 @@ namespace SixLabors.ImageSharp.PixelFormats { GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); - ref Rgb24 sourceRef = ref source.DangerousGetPinnableReference(); - ref TPixel destRef = ref destPixels.DangerousGetPinnableReference(); + ref Rgb24 sourceRef = ref MemoryMarshal.GetReference(source); + ref TPixel destRef = ref MemoryMarshal.GetReference(destPixels); Rgba32 rgba = new Rgba32(0, 0, 0, 255); @@ -199,8 +200,8 @@ namespace SixLabors.ImageSharp.PixelFormats { GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); - ref TPixel sourceBaseRef = ref sourcePixels.DangerousGetPinnableReference(); - ref Rgb24 destBaseRef = ref dest.DangerousGetPinnableReference(); + ref TPixel sourceBaseRef = ref MemoryMarshal.GetReference(sourcePixels); + ref Rgb24 destBaseRef = ref MemoryMarshal.GetReference(dest); for (int i = 0; i < count; i++) { @@ -233,8 +234,8 @@ namespace SixLabors.ImageSharp.PixelFormats { GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); - ref Bgr24 sourceRef = ref source.DangerousGetPinnableReference(); - ref TPixel destRef = ref destPixels.DangerousGetPinnableReference(); + ref Bgr24 sourceRef = ref MemoryMarshal.GetReference(source); + ref TPixel destRef = ref MemoryMarshal.GetReference(destPixels); Rgba32 rgba = new Rgba32(0, 0, 0, 255); @@ -270,8 +271,8 @@ namespace SixLabors.ImageSharp.PixelFormats { GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); - ref TPixel sourceBaseRef = ref sourcePixels.DangerousGetPinnableReference(); - ref Bgr24 destBaseRef = ref dest.DangerousGetPinnableReference(); + ref TPixel sourceBaseRef = ref MemoryMarshal.GetReference(sourcePixels); + ref Bgr24 destBaseRef = ref MemoryMarshal.GetReference(dest); for (int i = 0; i < count; i++) { diff --git a/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.tt b/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.tt index aa88b6606c..365f5cb514 100644 --- a/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.tt +++ b/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.tt @@ -7,6 +7,7 @@ <#@ import namespace="System.Linq" #> <#@ import namespace="System.Text" #> <#@ import namespace="System.Collections.Generic" #> +<#@ import namespace="System.Runtime.InteropServices" #> <#@ output extension=".cs" #> <# void GenerateToDestFormatMethods(string pixelType) @@ -24,8 +25,8 @@ { GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); - ref TPixel sourceBaseRef = ref sourcePixels.DangerousGetPinnableReference(); - ref <#=pixelType#> destBaseRef = ref dest.DangerousGetPinnableReference(); + ref TPixel sourceBaseRef = ref MemoryMarshal.GetReference(sourcePixels); + ref <#=pixelType#> destBaseRef = ref MemoryMarshal.GetReference(dest); for (int i = 0; i < count; i++) { @@ -64,8 +65,8 @@ { GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); - ref <#=pixelType#> sourceRef = ref source.DangerousGetPinnableReference(); - ref TPixel destRef = ref destPixels.DangerousGetPinnableReference(); + ref <#=pixelType#> sourceRef = ref MemoryMarshal.GetReference(source); + ref TPixel destRef = ref MemoryMarshal.GetReference(destPixels); Rgba32 rgba = new Rgba32(0, 0, 0, 255); @@ -101,7 +102,8 @@ namespace SixLabors.ImageSharp.PixelFormats { using System; using System.Runtime.CompilerServices; - + using System.Runtime.InteropServices; + public partial class PixelOperations { <# diff --git a/src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.cs index 659e702281..edf6a88e1f 100644 --- a/src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.cs @@ -6,9 +6,9 @@ namespace SixLabors.ImageSharp { using System; using System.Runtime.CompilerServices; - + using System.Runtime.InteropServices; using SixLabors.ImageSharp.PixelFormats; - + /// /// Provides optimized overrides for bulk operations. /// @@ -22,8 +22,8 @@ namespace SixLabors.ImageSharp { GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); - ref Rgb24 sourceRef = ref source.DangerousGetPinnableReference(); - ref Rgba32 destRef = ref destPixels.DangerousGetPinnableReference(); + ref Rgb24 sourceRef = ref MemoryMarshal.GetReference(source); + ref Rgba32 destRef = ref MemoryMarshal.GetReference(destPixels); for (int i = 0; i < count; i++) { @@ -38,8 +38,8 @@ namespace SixLabors.ImageSharp { GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); - ref Rgba32 sourceRef = ref sourcePixels.DangerousGetPinnableReference(); - ref Rgb24 destRef = ref dest.DangerousGetPinnableReference(); + ref Rgba32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); + ref Rgb24 destRef = ref MemoryMarshal.GetReference(dest); for (int i = 0; i < count; i++) { @@ -54,8 +54,8 @@ namespace SixLabors.ImageSharp { GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); - ref Bgr24 sourceRef = ref source.DangerousGetPinnableReference(); - ref Rgba32 destRef = ref destPixels.DangerousGetPinnableReference(); + ref Bgr24 sourceRef = ref MemoryMarshal.GetReference(source); + ref Rgba32 destRef = ref MemoryMarshal.GetReference(destPixels); for (int i = 0; i < count; i++) { @@ -70,8 +70,8 @@ namespace SixLabors.ImageSharp { GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); - ref Rgba32 sourceRef = ref sourcePixels.DangerousGetPinnableReference(); - ref Bgr24 destRef = ref dest.DangerousGetPinnableReference(); + ref Rgba32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); + ref Bgr24 destRef = ref MemoryMarshal.GetReference(dest); for (int i = 0; i < count; i++) { @@ -86,8 +86,8 @@ namespace SixLabors.ImageSharp { GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); - ref Bgra32 sourceRef = ref source.DangerousGetPinnableReference(); - ref Rgba32 destRef = ref destPixels.DangerousGetPinnableReference(); + ref Bgra32 sourceRef = ref MemoryMarshal.GetReference(source); + ref Rgba32 destRef = ref MemoryMarshal.GetReference(destPixels); for (int i = 0; i < count; i++) { @@ -102,8 +102,8 @@ namespace SixLabors.ImageSharp { GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); - ref Rgba32 sourceRef = ref sourcePixels.DangerousGetPinnableReference(); - ref Bgra32 destRef = ref dest.DangerousGetPinnableReference(); + ref Rgba32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); + ref Bgra32 destRef = ref MemoryMarshal.GetReference(dest); for (int i = 0; i < count; i++) { diff --git a/src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.tt b/src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.tt index 9d22293947..d83e49f770 100644 --- a/src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.tt +++ b/src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.tt @@ -18,8 +18,8 @@ { GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); - ref <#=pixelType#> sourceRef = ref source.DangerousGetPinnableReference(); - ref Rgba32 destRef = ref destPixels.DangerousGetPinnableReference(); + ref <#=pixelType#> sourceRef = ref MemoryMarshal.GetReference(source); + ref Rgba32 destRef = ref MemoryMarshal.GetReference(destPixels); for (int i = 0; i < count; i++) { @@ -40,8 +40,8 @@ { GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); - ref Rgba32 sourceRef = ref sourcePixels.DangerousGetPinnableReference(); - ref <#=pixelType#> destRef = ref dest.DangerousGetPinnableReference(); + ref Rgba32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); + ref <#=pixelType#> destRef = ref MemoryMarshal.GetReference(dest); for (int i = 0; i < count; i++) { @@ -61,9 +61,9 @@ namespace SixLabors.ImageSharp { using System; using System.Runtime.CompilerServices; - + using System.Runtime.InteropServices; using SixLabors.ImageSharp.PixelFormats; - + /// /// Provides optimized overrides for bulk operations. /// diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs index 4f879fbdc7..6f79752406 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs @@ -4,6 +4,7 @@ using System; using System.Numerics; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace SixLabors.ImageSharp.PixelFormats { @@ -30,8 +31,8 @@ namespace SixLabors.ImageSharp.PixelFormats { GuardSpans(sourceVectors, nameof(sourceVectors), destColors, nameof(destColors), count); - ref Vector4 sourceRef = ref sourceVectors.DangerousGetPinnableReference(); - ref TPixel destRef = ref destColors.DangerousGetPinnableReference(); + ref Vector4 sourceRef = ref MemoryMarshal.GetReference(sourceVectors); + ref TPixel destRef = ref MemoryMarshal.GetReference(destColors); for (int i = 0; i < count; i++) { @@ -51,8 +52,8 @@ namespace SixLabors.ImageSharp.PixelFormats { GuardSpans(sourceColors, nameof(sourceColors), destVectors, nameof(destVectors), count); - ref TPixel sourceRef = ref sourceColors.DangerousGetPinnableReference(); - ref Vector4 destRef = ref destVectors.DangerousGetPinnableReference(); + ref TPixel sourceRef = ref MemoryMarshal.GetReference(sourceColors); + ref Vector4 destRef = ref MemoryMarshal.GetReference(destVectors); for (int i = 0; i < count; i++) { diff --git a/src/ImageSharp/PixelFormats/Rgba32.PixelOperations.cs b/src/ImageSharp/PixelFormats/Rgba32.PixelOperations.cs index 552ac0a018..89a4aba264 100644 --- a/src/ImageSharp/PixelFormats/Rgba32.PixelOperations.cs +++ b/src/ImageSharp/PixelFormats/Rgba32.PixelOperations.cs @@ -57,8 +57,8 @@ namespace SixLabors.ImageSharp int unpackedRawCount = count * 4; - ref uint sourceBase = ref Unsafe.As(ref sourceColors.DangerousGetPinnableReference()); - ref UnpackedRGBA destBaseAsUnpacked = ref Unsafe.As(ref destVectors.DangerousGetPinnableReference()); + ref uint sourceBase = ref Unsafe.As(ref MemoryMarshal.GetReference(sourceColors)); + ref UnpackedRGBA destBaseAsUnpacked = ref Unsafe.As(ref MemoryMarshal.GetReference(destVectors)); ref Vector destBaseAsUInt = ref Unsafe.As>(ref destBaseAsUnpacked); ref Vector destBaseAsFloat = ref Unsafe.As>(ref destBaseAsUnpacked); diff --git a/src/ImageSharp/Processing/Processors/Dithering/PixelPair.cs b/src/ImageSharp/Processing/Processors/Dithering/PixelPair.cs index e3b9c11bdf..07045bb5ab 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/PixelPair.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/PixelPair.cs @@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.Processing.Processors /// Represents a composite pair of pixels. Used for caching color distance lookups. /// /// The pixel format. - internal struct PixelPair : IEquatable> + internal readonly struct PixelPair : IEquatable> where TPixel : struct, IPixel { /// diff --git a/src/ImageSharp/Processing/Processors/Transforms/WeightsWindow.cs b/src/ImageSharp/Processing/Processors/Transforms/WeightsWindow.cs index 399b3db842..26aaec502f 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/WeightsWindow.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/WeightsWindow.cs @@ -4,7 +4,7 @@ using System; using System.Numerics; using System.Runtime.CompilerServices; - +using System.Runtime.InteropServices; using SixLabors.ImageSharp.Memory; namespace SixLabors.ImageSharp.Processing.Processors @@ -79,7 +79,7 @@ namespace SixLabors.ImageSharp.Processing.Processors { ref float horizontalValues = ref this.GetStartReference(); int left = this.Left; - ref Vector4 vecPtr = ref Unsafe.Add(ref rowSpan.DangerousGetPinnableReference(), left + sourceX); + ref Vector4 vecPtr = ref Unsafe.Add(ref MemoryMarshal.GetReference(rowSpan), left + sourceX); // Destination color components Vector4 result = Vector4.Zero; @@ -106,7 +106,7 @@ namespace SixLabors.ImageSharp.Processing.Processors { ref float horizontalValues = ref this.GetStartReference(); int left = this.Left; - ref Vector4 vecPtr = ref Unsafe.Add(ref rowSpan.DangerousGetPinnableReference(), left + sourceX); + ref Vector4 vecPtr = ref Unsafe.Add(ref MemoryMarshal.GetReference(rowSpan), left + sourceX); // Destination color components Vector4 result = Vector4.Zero; diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/PackFromVector4.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/PackFromVector4.cs index 7d8519875b..7bac44a982 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/PackFromVector4.cs +++ b/tests/ImageSharp.Benchmarks/Color/Bulk/PackFromVector4.cs @@ -3,7 +3,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Color.Bulk { using System.Numerics; using System.Runtime.CompilerServices; - + using System.Runtime.InteropServices; using BenchmarkDotNet.Attributes; using SixLabors.ImageSharp.Memory; @@ -37,8 +37,8 @@ namespace SixLabors.ImageSharp.Benchmarks.Color.Bulk [Benchmark(Baseline = true)] public void PerElement() { - ref Vector4 s = ref this.source.Span.DangerousGetPinnableReference(); - ref TPixel d = ref this.destination.Span.DangerousGetPinnableReference(); + ref Vector4 s = ref MemoryMarshal.GetReference(this.source.Span); + ref TPixel d = ref MemoryMarshal.GetReference(this.destination.Span); for (int i = 0; i < this.Count; i++) { diff --git a/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj b/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj index ceec8f6fb2..62fd11e8e4 100644 --- a/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj +++ b/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj @@ -23,7 +23,12 @@ + + + + + diff --git a/tests/ImageSharp.Tests/ConfigurationTests.cs b/tests/ImageSharp.Tests/ConfigurationTests.cs index 06f02fcf16..cf348569ce 100644 --- a/tests/ImageSharp.Tests/ConfigurationTests.cs +++ b/tests/ImageSharp.Tests/ConfigurationTests.cs @@ -22,8 +22,10 @@ namespace SixLabors.ImageSharp.Tests public Configuration DefaultConfiguration { get; private set; } public ConfigurationTests() - { - this.DefaultConfiguration = Configuration.CreateDefaultInstance(); + { + // the shallow copy of configuration should behave exactly like the default configuration, + // so by using the copy, we test both the default and the copy. + this.DefaultConfiguration = Configuration.CreateDefaultInstance().ShallowCopy(); this.ConfigurationEmpty = new Configuration(); } @@ -32,14 +34,7 @@ namespace SixLabors.ImageSharp.Tests { Assert.IsType(this.DefaultConfiguration.FileSystem); Assert.IsType(this.ConfigurationEmpty.FileSystem); - } - - [Fact] - public void IfAutoloadWellknwonFormatesIsTrueAllFormateAreLoaded() - { - Assert.Equal(4, this.DefaultConfiguration.ImageEncoders.Count()); - Assert.Equal(4, this.DefaultConfiguration.ImageDecoders.Count()); - } + } /// /// Test that the default configuration is not null. @@ -78,80 +73,6 @@ namespace SixLabors.ImageSharp.Tests Assert.True(Configuration.Default.ParallelOptions.MaxDegreeOfParallelism == Environment.ProcessorCount); } - [Fact] - public void AddImageFormatDetectorNullthrows() - { - Assert.Throws(() => - { - this.DefaultConfiguration.AddImageFormatDetector(null); - }); - } - - [Fact] - public void RegisterNullMimeTypeEncoder() - { - Assert.Throws(() => - { - this.DefaultConfiguration.SetEncoder(null, new Mock().Object); - }); - Assert.Throws(() => - { - this.DefaultConfiguration.SetEncoder(ImageFormats.Bmp, null); - }); - Assert.Throws(() => - { - this.DefaultConfiguration.SetEncoder(null, null); - }); - } - - [Fact] - public void RegisterNullSetDecoder() - { - Assert.Throws(() => - { - this.DefaultConfiguration.SetDecoder(null, new Mock().Object); - }); - Assert.Throws(() => - { - this.DefaultConfiguration.SetDecoder(ImageFormats.Bmp, null); - }); - Assert.Throws(() => - { - this.DefaultConfiguration.SetDecoder(null, null); - }); - } - - [Fact] - public void RegisterMimeTypeEncoderReplacesLast() - { - IImageEncoder encoder1 = new Mock().Object; - this.ConfigurationEmpty.SetEncoder(TestFormat.GlobalTestFormat, encoder1); - IImageEncoder found = this.ConfigurationEmpty.FindEncoder(TestFormat.GlobalTestFormat); - Assert.Equal(encoder1, found); - - IImageEncoder encoder2 = new Mock().Object; - this.ConfigurationEmpty.SetEncoder(TestFormat.GlobalTestFormat, encoder2); - IImageEncoder found2 = this.ConfigurationEmpty.FindEncoder(TestFormat.GlobalTestFormat); - Assert.Equal(encoder2, found2); - Assert.NotEqual(found, found2); - } - - [Fact] - public void RegisterMimeTypeDecoderReplacesLast() - { - IImageDecoder decoder1 = new Mock().Object; - this.ConfigurationEmpty.SetDecoder(TestFormat.GlobalTestFormat, decoder1); - IImageDecoder found = this.ConfigurationEmpty.FindDecoder(TestFormat.GlobalTestFormat); - Assert.Equal(decoder1, found); - - IImageDecoder decoder2 = new Mock().Object; - this.ConfigurationEmpty.SetDecoder(TestFormat.GlobalTestFormat, decoder2); - IImageDecoder found2 = this.ConfigurationEmpty.FindDecoder(TestFormat.GlobalTestFormat); - Assert.Equal(decoder2, found2); - Assert.NotEqual(found, found2); - } - - [Fact] public void ConstructorCallConfigureOnFormatProvider() { diff --git a/tests/ImageSharp.Tests/Formats/ImageFormatManagerTests.cs b/tests/ImageSharp.Tests/Formats/ImageFormatManagerTests.cs new file mode 100644 index 0000000000..a6f6600f05 --- /dev/null +++ b/tests/ImageSharp.Tests/Formats/ImageFormatManagerTests.cs @@ -0,0 +1,129 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using SixLabors.ImageSharp.Formats; +using SixLabors.ImageSharp.IO; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Formats.Png; +using SixLabors.ImageSharp.Formats.Bmp; +using SixLabors.ImageSharp.Formats.Jpeg; +using SixLabors.ImageSharp.Formats.Gif; +using Moq; +using Xunit; + + +namespace SixLabors.ImageSharp.Tests +{ + public class ImageFormatManagerTests + { + public ImageFormatManager FormatsManagerEmpty { get; private set; } + public ImageFormatManager DefaultFormatsManager { get; private set; } + + public ImageFormatManagerTests() + { + this.DefaultFormatsManager = Configuration.Default.ImageFormatsManager; + this.FormatsManagerEmpty = new ImageFormatManager(); + } + + [Fact] + public void IfAutoloadWellKnownFormatsIsTrueAllFormatsAreLoaded() + { + Assert.Equal(1, this.DefaultFormatsManager.ImageEncoders.Select(item => item.Value).OfType().Count()); + Assert.Equal(1, this.DefaultFormatsManager.ImageEncoders.Select(item => item.Value).OfType().Count()); + Assert.Equal(1, this.DefaultFormatsManager.ImageEncoders.Select(item => item.Value).OfType().Count()); + Assert.Equal(1, this.DefaultFormatsManager.ImageEncoders.Select(item => item.Value).OfType().Count()); + + Assert.Equal(1, this.DefaultFormatsManager.ImageDecoders.Select(item => item.Value).OfType().Count()); + Assert.Equal(1, this.DefaultFormatsManager.ImageDecoders.Select(item => item.Value).OfType().Count()); + Assert.Equal(1, this.DefaultFormatsManager.ImageDecoders.Select(item => item.Value).OfType().Count()); + Assert.Equal(1, this.DefaultFormatsManager.ImageDecoders.Select(item => item.Value).OfType().Count()); + } + + [Fact] + public void AddImageFormatDetectorNullthrows() + { + Assert.Throws(() => + { + this.DefaultFormatsManager.AddImageFormatDetector(null); + }); + } + + [Fact] + public void RegisterNullMimeTypeEncoder() + { + Assert.Throws(() => + { + this.DefaultFormatsManager.SetEncoder(null, new Mock().Object); + }); + Assert.Throws(() => + { + this.DefaultFormatsManager.SetEncoder(ImageFormats.Bmp, null); + }); + Assert.Throws(() => + { + this.DefaultFormatsManager.SetEncoder(null, null); + }); + } + + [Fact] + public void RegisterNullSetDecoder() + { + Assert.Throws(() => + { + this.DefaultFormatsManager.SetDecoder(null, new Mock().Object); + }); + Assert.Throws(() => + { + this.DefaultFormatsManager.SetDecoder(ImageFormats.Bmp, null); + }); + Assert.Throws(() => + { + this.DefaultFormatsManager.SetDecoder(null, null); + }); + } + + [Fact] + public void RegisterMimeTypeEncoderReplacesLast() + { + IImageEncoder encoder1 = new Mock().Object; + this.FormatsManagerEmpty.SetEncoder(TestFormat.GlobalTestFormat, encoder1); + IImageEncoder found = this.FormatsManagerEmpty.FindEncoder(TestFormat.GlobalTestFormat); + Assert.Equal(encoder1, found); + + IImageEncoder encoder2 = new Mock().Object; + this.FormatsManagerEmpty.SetEncoder(TestFormat.GlobalTestFormat, encoder2); + IImageEncoder found2 = this.FormatsManagerEmpty.FindEncoder(TestFormat.GlobalTestFormat); + Assert.Equal(encoder2, found2); + Assert.NotEqual(found, found2); + } + + [Fact] + public void RegisterMimeTypeDecoderReplacesLast() + { + IImageDecoder decoder1 = new Mock().Object; + this.FormatsManagerEmpty.SetDecoder(TestFormat.GlobalTestFormat, decoder1); + IImageDecoder found = this.FormatsManagerEmpty.FindDecoder(TestFormat.GlobalTestFormat); + Assert.Equal(decoder1, found); + + IImageDecoder decoder2 = new Mock().Object; + this.FormatsManagerEmpty.SetDecoder(TestFormat.GlobalTestFormat, decoder2); + IImageDecoder found2 = this.FormatsManagerEmpty.FindDecoder(TestFormat.GlobalTestFormat); + Assert.Equal(decoder2, found2); + Assert.NotEqual(found, found2); + } + + [Fact] + public void AddFormatCallsConfig() + { + var provider = new Mock(); + var config = new Configuration(); + config.Configure(provider.Object); + + provider.Verify(x => x.Configure(config)); + } + } +} diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs index 139fa351bb..95ee40e807 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs @@ -42,7 +42,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg TestImages.Jpeg.Baseline.Jpeg444, TestImages.Jpeg.Baseline.Bad.BadEOF, TestImages.Jpeg.Issues.MultiHuffmanBaseline394, - TestImages.Jpeg.Baseline.MultiScanBaselineCMYK + TestImages.Jpeg.Baseline.MultiScanBaselineCMYK, + TestImages.Jpeg.Baseline.Bad.BadRST }; public static string[] ProgressiveTestJpegs = @@ -61,6 +62,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg [TestImages.Jpeg.Baseline.Calliphora] = 0.00002f / 100, [TestImages.Jpeg.Baseline.Bad.BadEOF] = 0.38f / 100, [TestImages.Jpeg.Baseline.Testorig420] = 0.38f / 100, + [TestImages.Jpeg.Baseline.Bad.BadRST] = 0.0589f / 100, // Progressive: [TestImages.Jpeg.Issues.MissingFF00ProgressiveGirl159] = 0.34f / 100, @@ -119,7 +121,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg } public const string DecodeBaselineJpegOutputName = "DecodeBaselineJpeg"; - + [Theory] [WithFile(TestImages.Jpeg.Baseline.Calliphora, CommonNonDefaultPixelTypes, false)] [WithFile(TestImages.Jpeg.Baseline.Calliphora, CommonNonDefaultPixelTypes, true)] diff --git a/tests/ImageSharp.Tests/Image/ImageDiscoverMimeType.cs b/tests/ImageSharp.Tests/Image/ImageDiscoverMimeType.cs index f19fa1990c..1a2275062e 100644 --- a/tests/ImageSharp.Tests/Image/ImageDiscoverMimeType.cs +++ b/tests/ImageSharp.Tests/Image/ImageDiscoverMimeType.cs @@ -40,7 +40,7 @@ namespace SixLabors.ImageSharp.Tests FileSystem = this.fileSystem.Object }; - this.LocalConfiguration.AddImageFormatDetector(this.localMimeTypeDetector); + this.LocalConfiguration.ImageFormatsManager.AddImageFormatDetector(this.localMimeTypeDetector); TestFormat.RegisterGlobalTestFormat(); this.Marker = Guid.NewGuid().ToByteArray(); diff --git a/tests/ImageSharp.Tests/Image/ImageLoadTests.cs b/tests/ImageSharp.Tests/Image/ImageLoadTests.cs index de18714e2b..97274e98b3 100644 --- a/tests/ImageSharp.Tests/Image/ImageLoadTests.cs +++ b/tests/ImageSharp.Tests/Image/ImageLoadTests.cs @@ -54,8 +54,8 @@ namespace SixLabors.ImageSharp.Tests { FileSystem = this.fileSystem.Object }; - this.LocalConfiguration.AddImageFormatDetector(this.localMimeTypeDetector); - this.LocalConfiguration.SetDecoder(this.localImageFormatMock.Object, this.localDecoder.Object); + this.LocalConfiguration.ImageFormatsManager.AddImageFormatDetector(this.localMimeTypeDetector); + this.LocalConfiguration.ImageFormatsManager.SetDecoder(this.localImageFormatMock.Object, this.localDecoder.Object); TestFormat.RegisterGlobalTestFormat(); this.Marker = Guid.NewGuid().ToByteArray(); diff --git a/tests/ImageSharp.Tests/Image/ImageSaveTests.cs b/tests/ImageSharp.Tests/Image/ImageSaveTests.cs index 7f6e3b7dac..028313e631 100644 --- a/tests/ImageSharp.Tests/Image/ImageSaveTests.cs +++ b/tests/ImageSharp.Tests/Image/ImageSaveTests.cs @@ -42,8 +42,8 @@ namespace SixLabors.ImageSharp.Tests { FileSystem = this.fileSystem.Object }; - config.AddImageFormatDetector(this.localMimeTypeDetector); - config.SetEncoder(this.localImageFormat.Object, this.encoder.Object); + config.ImageFormatsManager.AddImageFormatDetector(this.localMimeTypeDetector); + config.ImageFormatsManager.SetEncoder(this.localImageFormat.Object, this.encoder.Object); this.Image = new Image(config, 1, 1); } diff --git a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj index 16f062c6ef..d6ea4a130f 100644 --- a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj +++ b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj @@ -16,7 +16,8 @@ - + + diff --git a/tests/ImageSharp.Tests/Memory/ArrayPoolMemoryManagerTests.cs b/tests/ImageSharp.Tests/Memory/ArrayPoolMemoryManagerTests.cs index a199bb319d..c73ce96313 100644 --- a/tests/ImageSharp.Tests/Memory/ArrayPoolMemoryManagerTests.cs +++ b/tests/ImageSharp.Tests/Memory/ArrayPoolMemoryManagerTests.cs @@ -133,7 +133,7 @@ namespace SixLabors.ImageSharp.Tests.Memory public void ReleaseRetainedResources_ReplacesInnerArrayPool(bool keepBufferAlive) { IBuffer buffer = this.MemoryManager.Allocate(32); - ref int ptrToPrev0 = ref buffer.Span.DangerousGetPinnableReference(); + ref int ptrToPrev0 = ref MemoryMarshal.GetReference(buffer.Span); if (!keepBufferAlive) { diff --git a/tests/ImageSharp.Tests/Memory/Buffer2DTests.cs b/tests/ImageSharp.Tests/Memory/Buffer2DTests.cs index 565e06572b..82163d2bb4 100644 --- a/tests/ImageSharp.Tests/Memory/Buffer2DTests.cs +++ b/tests/ImageSharp.Tests/Memory/Buffer2DTests.cs @@ -5,7 +5,7 @@ namespace SixLabors.ImageSharp.Tests.Memory { using System; using System.Runtime.CompilerServices; - + using System.Runtime.InteropServices; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Tests.Common; using SixLabors.Primitives; @@ -20,7 +20,7 @@ namespace SixLabors.ImageSharp.Tests.Memory public static void SpanPointsTo(Span span, IBuffer buffer, int bufferOffset = 0) where T : struct { - ref T actual = ref span.DangerousGetPinnableReference(); + ref T actual = ref MemoryMarshal.GetReference(span); ref T expected = ref Unsafe.Add(ref buffer.DangerousGetPinnableReference(), bufferOffset); Assert.True(Unsafe.AreSame(ref expected, ref actual), "span does not point to the expected position"); diff --git a/tests/ImageSharp.Tests/Memory/BufferTestSuite.cs b/tests/ImageSharp.Tests/Memory/BufferTestSuite.cs index 50477cb5cf..eff1f197a0 100644 --- a/tests/ImageSharp.Tests/Memory/BufferTestSuite.cs +++ b/tests/ImageSharp.Tests/Memory/BufferTestSuite.cs @@ -3,6 +3,7 @@ using System; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using SixLabors.ImageSharp.Memory; using Xunit; // ReSharper disable InconsistentNaming @@ -165,9 +166,9 @@ namespace SixLabors.ImageSharp.Tests.Memory { using (IBuffer buffer = this.Allocate(desiredLength, false, testManagedByteBuffer)) { - ref T a = ref buffer.Span.DangerousGetPinnableReference(); - ref T b = ref buffer.Span.DangerousGetPinnableReference(); - ref T c = ref buffer.Span.DangerousGetPinnableReference(); + ref T a = ref MemoryMarshal.GetReference(buffer.Span); + ref T b = ref MemoryMarshal.GetReference(buffer.Span); + ref T c = ref MemoryMarshal.GetReference(buffer.Span); Assert.True(Unsafe.AreSame(ref a, ref b)); Assert.True(Unsafe.AreSame(ref b, ref c)); diff --git a/tests/ImageSharp.Tests/Memory/SpanUtilityTests.cs b/tests/ImageSharp.Tests/Memory/SpanUtilityTests.cs index 049c4c6ba9..23bc297436 100644 --- a/tests/ImageSharp.Tests/Memory/SpanUtilityTests.cs +++ b/tests/ImageSharp.Tests/Memory/SpanUtilityTests.cs @@ -78,8 +78,8 @@ namespace SixLabors.ImageSharp.Tests.Memory TestStructs.Foo[] source = TestStructs.Foo.CreateArray(count + 2); TestStructs.Foo[] dest = new TestStructs.Foo[count + 5]; - var apSource = new Span(source, 1); - var apDest = new Span(dest, 1); + var apSource = new Span(source, 1, source.Length - 1); + var apDest = new Span(dest, 1, dest.Length - 1); SpanHelper.Copy(apSource, apDest, count - 1); @@ -101,8 +101,8 @@ namespace SixLabors.ImageSharp.Tests.Memory TestStructs.AlignedFoo[] source = TestStructs.AlignedFoo.CreateArray(count + 2); TestStructs.AlignedFoo[] dest = new TestStructs.AlignedFoo[count + 5]; - var apSource = new Span(source, 1); - var apDest = new Span(dest, 1); + var apSource = new Span(source, 1, source.Length - 1); + var apDest = new Span(dest, 1, dest.Length - 1); SpanHelper.Copy(apSource, apDest, count - 1); @@ -124,8 +124,8 @@ namespace SixLabors.ImageSharp.Tests.Memory int[] source = CreateTestInts(count + 2); int[] dest = new int[count + 5]; - var apSource = new Span(source, 1); - var apDest = new Span(dest, 1); + var apSource = new Span(source, 1, source.Length - 1); + var apDest = new Span(dest, 1, dest.Length - 1); SpanHelper.Copy(apSource, apDest, count - 1); @@ -148,8 +148,8 @@ namespace SixLabors.ImageSharp.Tests.Memory TestStructs.Foo[] source = TestStructs.Foo.CreateArray(count + 2); byte[] dest = new byte[destCount + sizeof(TestStructs.Foo) * 2]; - var apSource = new Span(source, 1); - var apDest = new Span(dest, sizeof(TestStructs.Foo)); + var apSource = new Span(source, 1, source.Length - 1); + var apDest = new Span(dest, sizeof(TestStructs.Foo), dest.Length - sizeof(TestStructs.Foo)); SpanHelper.Copy(apSource.AsBytes(), apDest, (count - 1) * sizeof(TestStructs.Foo)); @@ -171,8 +171,8 @@ namespace SixLabors.ImageSharp.Tests.Memory TestStructs.AlignedFoo[] source = TestStructs.AlignedFoo.CreateArray(count + 2); byte[] dest = new byte[destCount + sizeof(TestStructs.AlignedFoo) * 2]; - var apSource = new Span(source, 1); - var apDest = new Span(dest, sizeof(TestStructs.AlignedFoo)); + var apSource = new Span(source, 1, source.Length - 1); + var apDest = new Span(dest, sizeof(TestStructs.AlignedFoo), dest.Length - sizeof(TestStructs.AlignedFoo)); SpanHelper.Copy(apSource.AsBytes(), apDest, (count - 1) * sizeof(TestStructs.AlignedFoo)); diff --git a/tests/ImageSharp.Tests/TestFormat.cs b/tests/ImageSharp.Tests/TestFormat.cs index 078b708dfd..445ace9812 100644 --- a/tests/ImageSharp.Tests/TestFormat.cs +++ b/tests/ImageSharp.Tests/TestFormat.cs @@ -116,9 +116,9 @@ namespace SixLabors.ImageSharp.Tests public void Configure(Configuration host) { - host.AddImageFormatDetector(new TestHeader(this)); - host.SetEncoder(this, new TestEncoder(this)); - host.SetDecoder(this, new TestDecoder(this)); + host.ImageFormatsManager.AddImageFormatDetector(new TestHeader(this)); + host.ImageFormatsManager.SetEncoder(this, new TestEncoder(this)); + host.ImageFormatsManager.SetDecoder(this, new TestDecoder(this)); } public struct DecodeOperation diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index f1f989581f..db469f87e1 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -96,6 +96,7 @@ namespace SixLabors.ImageSharp.Tests public static class Bad { public const string BadEOF = "Jpg/baseline/badeof.jpg"; + public const string BadRST = "Jpg/baseline/badrst.jpg"; } public const string Cmyk = "Jpg/baseline/cmyk.jpg"; diff --git a/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs b/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs index 089fed6b0a..fa9497a8f8 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs @@ -21,20 +21,20 @@ namespace SixLabors.ImageSharp.Tests internal static IImageDecoder GetReferenceDecoder(string filePath) { IImageFormat format = GetImageFormat(filePath); - return Configuration.FindDecoder(format); + return Configuration.ImageFormatsManager.FindDecoder(format); } internal static IImageEncoder GetReferenceEncoder(string filePath) { IImageFormat format = GetImageFormat(filePath); - return Configuration.FindEncoder(format); + return Configuration.ImageFormatsManager.FindEncoder(format); } internal static IImageFormat GetImageFormat(string filePath) { string extension = Path.GetExtension(filePath).ToLower(); if (extension[0] == '.') extension = extension.Substring(1); - IImageFormat format = Configuration.FindFormatByFileExtension(extension); + IImageFormat format = Configuration.ImageFormatsManager.FindFormatByFileExtension(extension); return format; } @@ -45,9 +45,9 @@ namespace SixLabors.ImageSharp.Tests IImageEncoder encoder, IImageFormatDetector detector) { - cfg.SetDecoder(imageFormat, decoder); - cfg.SetEncoder(imageFormat, encoder); - cfg.AddImageFormatDetector(detector); + cfg.ImageFormatsManager.SetDecoder(imageFormat, decoder); + cfg.ImageFormatsManager.SetEncoder(imageFormat, encoder); + cfg.ImageFormatsManager.AddImageFormatDetector(detector); } private static Configuration CreateDefaultConfiguration() diff --git a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs index 6014e25334..f03f9db09a 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs @@ -360,7 +360,7 @@ namespace SixLabors.ImageSharp.Tests IImageDecoder referenceDecoder = TestEnvironment.GetReferenceDecoder(path); IImageFormat format = TestEnvironment.GetImageFormat(path); - IImageDecoder defaultDecoder = Configuration.Default.FindDecoder(format); + IImageDecoder defaultDecoder = Configuration.Default.ImageFormatsManager.FindDecoder(format); //if (referenceDecoder.GetType() == defaultDecoder.GetType()) //{ diff --git a/tests/Images/External b/tests/Images/External index 8714b94dc4..653f0c7e3c 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit 8714b94dc4bab6788fcbb6254174db2b9c8f69c9 +Subproject commit 653f0c7e3c84657f68dd46e5a380186b3696b956 diff --git a/tests/Images/Input/Jpg/baseline/badrst.jpg b/tests/Images/Input/Jpg/baseline/badrst.jpg new file mode 100644 index 0000000000..61805b42d3 --- /dev/null +++ b/tests/Images/Input/Jpg/baseline/badrst.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:af18f0bf30231d2c4c0e6b80d4636237c2851f67763788de12931fd1960c4ff3 +size 74497