Browse Source

Merge branch 'master' into colorspace-transforms

pull/595/head
James Jackson-South 8 years ago
parent
commit
aa30806759
  1. 3
      src/ImageSharp/Advanced/AdvancedImageExtensions.cs
  2. 2
      src/ImageSharp/ColorSpaces/CieLab.cs
  3. 2
      src/ImageSharp/ColorSpaces/CieLch.cs
  4. 2
      src/ImageSharp/ColorSpaces/CieLchuv.cs
  5. 2
      src/ImageSharp/ColorSpaces/CieLuv.cs
  6. 2
      src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs
  7. 2
      src/ImageSharp/ColorSpaces/CieXyy.cs
  8. 2
      src/ImageSharp/ColorSpaces/CieXyz.cs
  9. 2
      src/ImageSharp/ColorSpaces/Cmyk.cs
  10. 2
      src/ImageSharp/ColorSpaces/Conversion/Implementation/RgbWorkingSpace.cs
  11. 2
      src/ImageSharp/ColorSpaces/Hsl.cs
  12. 2
      src/ImageSharp/ColorSpaces/Hsv.cs
  13. 2
      src/ImageSharp/ColorSpaces/HunterLab.cs
  14. 2
      src/ImageSharp/ColorSpaces/LinearRgb.cs
  15. 2
      src/ImageSharp/ColorSpaces/Lms.cs
  16. 2
      src/ImageSharp/ColorSpaces/Rgb.cs
  17. 2
      src/ImageSharp/ColorSpaces/YCbCr.cs
  18. 8
      src/ImageSharp/Common/Extensions/SimdUtils.cs
  19. 417
      src/ImageSharp/Configuration.cs
  20. 6
      src/ImageSharp/Formats/Bmp/BmpConfigurationModule.cs
  21. 2
      src/ImageSharp/Formats/Bmp/ImageExtensions.cs
  22. 6
      src/ImageSharp/Formats/Gif/GifConfigurationModule.cs
  23. 2
      src/ImageSharp/Formats/Gif/ImageExtensions.cs
  24. 2
      src/ImageSharp/Formats/Gif/PackedField.cs
  25. 186
      src/ImageSharp/Formats/ImageFormatManager.cs
  26. 5
      src/ImageSharp/Formats/Jpeg/Common/Block8x8.cs
  27. 4
      src/ImageSharp/Formats/Jpeg/Common/Block8x8F.cs
  28. 2
      src/ImageSharp/Formats/Jpeg/Common/Decoder/AdobeMarker.cs
  29. 9
      src/ImageSharp/Formats/Jpeg/Common/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimd.cs
  30. 9
      src/ImageSharp/Formats/Jpeg/Common/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimdAvx2.cs
  31. 4
      src/ImageSharp/Formats/Jpeg/Common/Decoder/ColorConverters/JpegColorConverter.cs
  32. 2
      src/ImageSharp/Formats/Jpeg/Common/Decoder/JFifMarker.cs
  33. 2
      src/ImageSharp/Formats/Jpeg/Common/GenericBlock8x8.cs
  34. 10
      src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/InputProcessor.cs
  35. 181
      src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigJpegScanDecoder.cs
  36. 2
      src/ImageSharp/Formats/Jpeg/GolangPort/Components/Encoder/HuffmanLut.cs
  37. 2
      src/ImageSharp/Formats/Jpeg/GolangPort/Components/Encoder/HuffmanSpec.cs
  38. 9
      src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs
  39. 2
      src/ImageSharp/Formats/Jpeg/ImageExtensions.cs
  40. 6
      src/ImageSharp/Formats/Jpeg/JpegConfigurationModule.cs
  41. 2
      src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsScanDecoder.cs
  42. 2
      src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsYCbCrToRgbTables.cs
  43. 2
      src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoderCore.cs
  44. 11
      src/ImageSharp/Formats/Png/Filters/AverageFilter.cs
  45. 11
      src/ImageSharp/Formats/Png/Filters/PaethFilter.cs
  46. 7
      src/ImageSharp/Formats/Png/Filters/SubFilter.cs
  47. 11
      src/ImageSharp/Formats/Png/Filters/UpFilter.cs
  48. 2
      src/ImageSharp/Formats/Png/ImageExtensions.cs
  49. 6
      src/ImageSharp/Formats/Png/PngConfigurationModule.cs
  50. 4
      src/ImageSharp/Formats/Png/PngDecoderCore.cs
  51. 4
      src/ImageSharp/Image/Image.Decode.cs
  52. 2
      src/ImageSharp/Image/Image.FromStream.cs
  53. 10
      src/ImageSharp/Image/ImageExtensions.cs
  54. 6
      src/ImageSharp/ImageSharp.csproj
  55. 2
      src/ImageSharp/Memory/BufferArea{T}.cs
  56. 3
      src/ImageSharp/Memory/BufferExtensions.cs
  57. 7
      src/ImageSharp/Memory/SpanHelper.cs
  58. 2
      src/ImageSharp/MetaData/Profiles/ICC/Various/IccColorantTableEntry.cs
  59. 2
      src/ImageSharp/MetaData/Profiles/ICC/Various/IccNamedColor.cs
  60. 2
      src/ImageSharp/MetaData/Profiles/ICC/Various/IccPositionNumber.cs
  61. 2
      src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileId.cs
  62. 2
      src/ImageSharp/MetaData/Profiles/ICC/Various/IccResponseNumber.cs
  63. 2
      src/ImageSharp/MetaData/Profiles/ICC/Various/IccScreeningChannel.cs
  64. 2
      src/ImageSharp/MetaData/Profiles/ICC/Various/IccTagTableEntry.cs
  65. 2
      src/ImageSharp/Numerics/ValueSize.cs
  66. 35
      src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.cs
  67. 12
      src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.tt
  68. 28
      src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.cs
  69. 12
      src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.tt
  70. 9
      src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs
  71. 4
      src/ImageSharp/PixelFormats/Rgba32.PixelOperations.cs
  72. 2
      src/ImageSharp/Processing/Processors/Dithering/PixelPair.cs
  73. 6
      src/ImageSharp/Processing/Processors/Transforms/WeightsWindow.cs
  74. 6
      tests/ImageSharp.Benchmarks/Color/Bulk/PackFromVector4.cs
  75. 5
      tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj
  76. 89
      tests/ImageSharp.Tests/ConfigurationTests.cs
  77. 129
      tests/ImageSharp.Tests/Formats/ImageFormatManagerTests.cs
  78. 6
      tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs
  79. 2
      tests/ImageSharp.Tests/Image/ImageDiscoverMimeType.cs
  80. 4
      tests/ImageSharp.Tests/Image/ImageLoadTests.cs
  81. 4
      tests/ImageSharp.Tests/Image/ImageSaveTests.cs
  82. 3
      tests/ImageSharp.Tests/ImageSharp.Tests.csproj
  83. 2
      tests/ImageSharp.Tests/Memory/ArrayPoolMemoryManagerTests.cs
  84. 4
      tests/ImageSharp.Tests/Memory/Buffer2DTests.cs
  85. 7
      tests/ImageSharp.Tests/Memory/BufferTestSuite.cs
  86. 20
      tests/ImageSharp.Tests/Memory/SpanUtilityTests.cs
  87. 6
      tests/ImageSharp.Tests/TestFormat.cs
  88. 1
      tests/ImageSharp.Tests/TestImages.cs
  89. 12
      tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs
  90. 2
      tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs
  91. 2
      tests/Images/External
  92. BIN
      tests/Images/Input/Jpg/baseline/badrst.jpg

3
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
/// <returns>A reference to the element.</returns>
private static ref TPixel DangerousGetPinnableReferenceToPixelBuffer<TPixel>(IPixelSource<TPixel> source)
where TPixel : struct, IPixel<TPixel>
=> ref source.PixelBuffer.Span.DangerousGetPinnableReference();
=> ref MemoryMarshal.GetReference(source.PixelBuffer.Span);
}
}

2
src/ImageSharp/ColorSpaces/CieLab.cs

@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// Represents a CIE L*a*b* 1976 color.
/// <see href="https://en.wikipedia.org/wiki/Lab_color_space"/>
/// </summary>
internal struct CieLab : IColorVector, IEquatable<CieLab>, IAlmostEquatable<CieLab, float>
internal readonly struct CieLab : IColorVector, IEquatable<CieLab>, IAlmostEquatable<CieLab, float>
{
/// <summary>
/// D50 standard illuminant.

2
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.
/// <see href="https://en.wikipedia.org/wiki/Lab_color_space#Cylindrical_representation:_CIELCh_or_CIEHLC"/>
/// </summary>
internal struct CieLch : IColorVector, IEquatable<CieLch>, IAlmostEquatable<CieLch, float>
internal readonly struct CieLch : IColorVector, IEquatable<CieLch>, IAlmostEquatable<CieLch, float>
{
/// <summary>
/// D50 standard illuminant.

2
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.
/// <see href="https://en.wikipedia.org/wiki/Lab_color_space#Cylindrical_representation:_CieLchuv_or_CIEHLC"/>
/// </summary>
internal struct CieLchuv : IColorVector, IEquatable<CieLchuv>, IAlmostEquatable<CieLchuv, float>
internal readonly struct CieLchuv : IColorVector, IEquatable<CieLchuv>, IAlmostEquatable<CieLchuv, float>
{
/// <summary>
/// D50 standard illuminant.

2
src/ImageSharp/ColorSpaces/CieLuv.cs

@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// attempted perceptual uniformity
/// <see href="https://en.wikipedia.org/wiki/CIELUV"/>
/// </summary>
internal struct CieLuv : IColorVector, IEquatable<CieLuv>, IAlmostEquatable<CieLuv, float>
internal readonly struct CieLuv : IColorVector, IEquatable<CieLuv>, IAlmostEquatable<CieLuv, float>
{
/// <summary>
/// D65 standard illuminant.

2
src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs

@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// <summary>
/// Represents the coordinates of CIEXY chromaticity space
/// </summary>
internal struct CieXyChromaticityCoordinates : IEquatable<CieXyChromaticityCoordinates>, IAlmostEquatable<CieXyChromaticityCoordinates, float>
internal readonly struct CieXyChromaticityCoordinates : IEquatable<CieXyChromaticityCoordinates>, IAlmostEquatable<CieXyChromaticityCoordinates, float>
{
/// <summary>
/// Represents a <see cref="CieXyChromaticityCoordinates"/> that has X, Y values set to zero.

2
src/ImageSharp/ColorSpaces/CieXyy.cs

@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// Represents an CIE xyY 1931 color
/// <see href="https://en.wikipedia.org/wiki/CIE_1931_color_space#CIE_xy_chromaticity_diagram_and_the_CIE_xyY_color_space"/>
/// </summary>
internal struct CieXyy : IColorVector, IEquatable<CieXyy>, IAlmostEquatable<CieXyy, float>
internal readonly struct CieXyy : IColorVector, IEquatable<CieXyy>, IAlmostEquatable<CieXyy, float>
{
/// <summary>
/// Represents a <see cref="CieXyy"/> that has X, Y, and Y values set to zero.

2
src/ImageSharp/ColorSpaces/CieXyz.cs

@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// Represents an CIE XYZ 1931 color
/// <see href="https://en.wikipedia.org/wiki/CIE_1931_color_space#Definition_of_the_CIE_XYZ_color_space"/>
/// </summary>
internal struct CieXyz : IColorVector, IEquatable<CieXyz>, IAlmostEquatable<CieXyz, float>
internal readonly struct CieXyz : IColorVector, IEquatable<CieXyz>, IAlmostEquatable<CieXyz, float>
{
/// <summary>
/// Represents a <see cref="CieXyz"/> that has X, Y, and Z values set to zero.

2
src/ImageSharp/ColorSpaces/Cmyk.cs

@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// <summary>
/// Represents an CMYK (cyan, magenta, yellow, keyline) color.
/// </summary>
internal struct Cmyk : IEquatable<Cmyk>, IAlmostEquatable<Cmyk, float>
internal readonly struct Cmyk : IEquatable<Cmyk>, IAlmostEquatable<Cmyk, float>
{
/// <summary>
/// Represents a <see cref="Cmyk"/> that has C, M, Y, and K values set to zero.

2
src/ImageSharp/ColorSpaces/Conversion/Implementation/RgbWorkingSpace.cs

@ -6,7 +6,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
/// <summary>
/// Trivial implementation of <see cref="IRgbWorkingSpace"/>
/// </summary>
internal struct RgbWorkingSpace : IRgbWorkingSpace
internal readonly struct RgbWorkingSpace : IRgbWorkingSpace
{
/// <summary>
/// Initializes a new instance of the <see cref="RgbWorkingSpace"/> struct.

2
src/ImageSharp/ColorSpaces/Hsl.cs

@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// <summary>
/// Represents a Hsl (hue, saturation, lightness) color.
/// </summary>
internal struct Hsl : IColorVector, IEquatable<Hsl>, IAlmostEquatable<Hsl, float>
internal readonly struct Hsl : IColorVector, IEquatable<Hsl>, IAlmostEquatable<Hsl, float>
{
/// <summary>
/// Represents a <see cref="Hsl"/> that has H, S, and L values set to zero.

2
src/ImageSharp/ColorSpaces/Hsv.cs

@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// <summary>
/// Represents a HSV (hue, saturation, value) color. Also known as HSB (hue, saturation, brightness).
/// </summary>
internal struct Hsv : IColorVector, IEquatable<Hsv>, IAlmostEquatable<Hsv, float>
internal readonly struct Hsv : IColorVector, IEquatable<Hsv>, IAlmostEquatable<Hsv, float>
{
/// <summary>
/// Represents a <see cref="Hsv"/> that has H, S, and V values set to zero.

2
src/ImageSharp/ColorSpaces/HunterLab.cs

@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// Represents an Hunter LAB color.
/// <see href="https://en.wikipedia.org/wiki/Lab_color_space"/>
/// </summary>
internal struct HunterLab : IColorVector, IEquatable<HunterLab>, IAlmostEquatable<HunterLab, float>
internal readonly struct HunterLab : IColorVector, IEquatable<HunterLab>, IAlmostEquatable<HunterLab, float>
{
/// <summary>
/// D50 standard illuminant.

2
src/ImageSharp/ColorSpaces/LinearRgb.cs

@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// <summary>
/// Represents an linear Rgb color with specified <see cref="IRgbWorkingSpace"/> working space
/// </summary>
internal struct LinearRgb : IColorVector, IEquatable<LinearRgb>, IAlmostEquatable<LinearRgb, float>
internal readonly struct LinearRgb : IColorVector, IEquatable<LinearRgb>, IAlmostEquatable<LinearRgb, float>
{
/// <summary>
/// Represents a <see cref="LinearRgb"/> that has R, G, and B values set to zero.

2
src/ImageSharp/ColorSpaces/Lms.cs

@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// named after their responsivity (sensitivity) at long, medium and short wavelengths.
/// <see href="https://en.wikipedia.org/wiki/LMS_color_space"/>
/// </summary>
internal struct Lms : IColorVector, IEquatable<Lms>, IAlmostEquatable<Lms, float>
internal readonly struct Lms : IColorVector, IEquatable<Lms>, IAlmostEquatable<Lms, float>
{
/// <summary>
/// Represents a <see cref="Lms"/> that has L, M, and S values set to zero.

2
src/ImageSharp/ColorSpaces/Rgb.cs

@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// <summary>
/// Represents an RGB color with specified <see cref="IRgbWorkingSpace"/> working space
/// </summary>
internal struct Rgb : IColorVector, IEquatable<Rgb>, IAlmostEquatable<Rgb, float>
internal readonly struct Rgb : IColorVector, IEquatable<Rgb>, IAlmostEquatable<Rgb, float>
{
/// <summary>
/// Represents a <see cref="Rgb"/> that has R, G, and B values set to zero.

2
src/ImageSharp/ColorSpaces/YCbCr.cs

@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// <see href="http://en.wikipedia.org/wiki/YCbCr"/>
/// <see href="http://www.ijg.org/files/T-REC-T.871-201105-I!!PDF-E.pdf"/>
/// </summary>
internal struct YCbCr : IColorVector, IEquatable<YCbCr>, IAlmostEquatable<YCbCr, float>
internal readonly struct YCbCr : IColorVector, IEquatable<YCbCr>, IAlmostEquatable<YCbCr, float>
{
/// <summary>
/// Represents a <see cref="YCbCr"/> that has Y, Cb, and Cr values set to zero.

8
src/ImageSharp/Common/Extensions/SimdUtils.cs

@ -76,8 +76,8 @@ namespace SixLabors.ImageSharp
return;
}
ref Vector<float> srcBase = ref Unsafe.As<float, Vector<float>>(ref source.DangerousGetPinnableReference());
ref Octet.OfByte destBase = ref Unsafe.As<byte, Octet.OfByte>(ref dest.DangerousGetPinnableReference());
ref Vector<float> srcBase = ref Unsafe.As<float, Vector<float>>(ref MemoryMarshal.GetReference(source));
ref Octet.OfByte destBase = ref Unsafe.As<byte, Octet.OfByte>(ref MemoryMarshal.GetReference(dest));
int n = source.Length / 8;
Vector<float> magick = new Vector<float>(32768.0f);
@ -117,8 +117,8 @@ namespace SixLabors.ImageSharp
return;
}
ref Vector<float> srcBase = ref Unsafe.As<float, Vector<float>>(ref source.DangerousGetPinnableReference());
ref Octet.OfByte destBase = ref Unsafe.As<byte, Octet.OfByte>(ref dest.DangerousGetPinnableReference());
ref Vector<float> srcBase = ref Unsafe.As<float, Vector<float>>(ref MemoryMarshal.GetReference(source));
ref Octet.OfByte destBase = ref Unsafe.As<byte, Octet.OfByte>(ref MemoryMarshal.GetReference(dest));
int n = source.Length / 8;
Vector<float> magick = new Vector<float>(32768.0f);

417
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
{
/// <summary>
/// Provides initialization code which allows extending the library.
/// </summary>
public sealed class Configuration
{
/// <summary>
/// A lazily initialized configuration default instance.
/// </summary>
private static readonly Lazy<Configuration> Lazy = new Lazy<Configuration>(CreateDefaultInstance);
/// <summary>
/// The list of supported <see cref="IImageEncoder"/> keyed to mime types.
/// </summary>
private readonly ConcurrentDictionary<IImageFormat, IImageEncoder> mimeTypeEncoders = new ConcurrentDictionary<IImageFormat, IImageEncoder>();
/// <summary>
/// The list of supported <see cref="IImageEncoder"/> keyed to mime types.
/// </summary>
private readonly ConcurrentDictionary<IImageFormat, IImageDecoder> mimeTypeDecoders = new ConcurrentDictionary<IImageFormat, IImageDecoder>();
/// <summary>
/// The list of supported <see cref="IImageFormat"/>s.
/// </summary>
private readonly ConcurrentBag<IImageFormat> imageFormats = new ConcurrentBag<IImageFormat>();
/// <summary>
/// The list of supported <see cref="IImageFormatDetector"/>s.
/// </summary>
private ConcurrentBag<IImageFormatDetector> imageFormatDetectors = new ConcurrentBag<IImageFormatDetector>();
/// <summary>
/// Initializes a new instance of the <see cref="Configuration" /> class.
/// </summary>
public Configuration()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Configuration" /> class.
/// </summary>
/// <param name="configurationModules">A collection of configuration modules to register</param>
public Configuration(params IConfigurationModule[] configurationModules)
{
if (configurationModules != null)
{
foreach (IConfigurationModule p in configurationModules)
{
p.Configure(this);
}
}
}
/// <summary>
/// Gets the default <see cref="Configuration"/> instance.
/// </summary>
public static Configuration Default { get; } = Lazy.Value;
/// <summary>
/// Gets the global parallel options for processing tasks in parallel.
/// </summary>
public ParallelOptions ParallelOptions { get; } = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount };
/// <summary>
/// Gets the currently registered <see cref="IImageFormat"/>s.
/// </summary>
public IEnumerable<IImageFormat> ImageFormats => this.imageFormats;
/// <summary>
/// Gets or sets the position in a stream to use for reading when using a seekable stream as an image data source.
/// </summary>
public ReadOrigin ReadOrigin { get; set; } = ReadOrigin.Current;
/// <summary>
/// Gets or sets the <see cref="MemoryManager"/> that is currently in use.
/// </summary>
public MemoryManager MemoryManager { get; set; } = ArrayPoolMemoryManager.CreateDefault();
/// <summary>
/// Gets the maximum header size of all the formats.
/// </summary>
internal int MaxHeaderSize { get; private set; }
/// <summary>
/// Gets the currently registered <see cref="IImageFormatDetector"/>s.
/// </summary>
internal IEnumerable<IImageFormatDetector> FormatDetectors => this.imageFormatDetectors;
/// <summary>
/// Gets the currently registered <see cref="IImageDecoder"/>s.
/// </summary>
internal IEnumerable<KeyValuePair<IImageFormat, IImageDecoder>> ImageDecoders => this.mimeTypeDecoders;
/// <summary>
/// Gets the currently registered <see cref="IImageEncoder"/>s.
/// </summary>
internal IEnumerable<KeyValuePair<IImageFormat, IImageEncoder>> ImageEncoders => this.mimeTypeEncoders;
#if !NETSTANDARD1_1
/// <summary>
/// Gets or sets the filesystem helper for accessing the local file system.
/// </summary>
internal IFileSystem FileSystem { get; set; } = new LocalFileSystem();
#endif
/// <summary>
/// Gets or sets the image operations provider factory.
/// </summary>
internal IImageProcessingContextFactory ImageOperationsProvider { get; set; } = new DefaultImageOperationsProviderFactory();
/// <summary>
/// Registers a new format provider.
/// </summary>
/// <param name="configuration">The configuration provider to call configure on.</param>
public void Configure(IConfigurationModule configuration)
{
Guard.NotNull(configuration, nameof(configuration));
configuration.Configure(this);
}
/// <summary>
/// Registers a new format provider.
/// </summary>
/// <param name="format">The format to register as a known format.</param>
public void AddImageFormat(IImageFormat format)
{
Guard.NotNull(format, nameof(format));
Guard.NotNull(format.MimeTypes, nameof(format.MimeTypes));
Guard.NotNull(format.FileExtensions, nameof(format.FileExtensions));
this.imageFormats.Add(format);
}
/// <summary>
/// For the specified file extensions type find the e <see cref="IImageFormat"/>.
/// </summary>
/// <param name="extension">The extension to discover</param>
/// <returns>The <see cref="IImageFormat"/> if found otherwise null</returns>
public IImageFormat FindFormatByFileExtension(string extension)
{
return this.imageFormats.FirstOrDefault(x => x.FileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase));
}
/// <summary>
/// For the specified mime type find the <see cref="IImageFormat"/>.
/// </summary>
/// <param name="mimeType">The mime-type to discover</param>
/// <returns>The <see cref="IImageFormat"/> if found; otherwise null</returns>
public IImageFormat FindFormatByMimeType(string mimeType)
{
return this.imageFormats.FirstOrDefault(x => x.MimeTypes.Contains(mimeType, StringComparer.OrdinalIgnoreCase));
}
/// <summary>
/// Sets a specific image encoder as the encoder for a specific image format.
/// </summary>
/// <param name="imageFormat">The image format to register the encoder for.</param>
/// <param name="encoder">The encoder to use,</param>
public void SetEncoder(IImageFormat imageFormat, IImageEncoder encoder)
{
Guard.NotNull(imageFormat, nameof(imageFormat));
Guard.NotNull(encoder, nameof(encoder));
this.AddImageFormat(imageFormat);
this.mimeTypeEncoders.AddOrUpdate(imageFormat, encoder, (s, e) => encoder);
}
/// <summary>
/// Sets a specific image decoder as the decoder for a specific image format.
/// </summary>
/// <param name="imageFormat">The image format to register the encoder for.</param>
/// <param name="decoder">The decoder to use,</param>
public void SetDecoder(IImageFormat imageFormat, IImageDecoder decoder)
{
Guard.NotNull(imageFormat, nameof(imageFormat));
Guard.NotNull(decoder, nameof(decoder));
this.AddImageFormat(imageFormat);
this.mimeTypeDecoders.AddOrUpdate(imageFormat, decoder, (s, e) => decoder);
}
/// <summary>
/// Removes all the registered image format detectors.
/// </summary>
public void ClearImageFormatDetectors()
{
this.imageFormatDetectors = new ConcurrentBag<IImageFormatDetector>();
}
/// <summary>
/// Adds a new detector for detecting mime types.
/// </summary>
/// <param name="detector">The detector to add</param>
public void AddImageFormatDetector(IImageFormatDetector detector)
{
Guard.NotNull(detector, nameof(detector));
this.imageFormatDetectors.Add(detector);
this.SetMaxHeaderSize();
}
/// <summary>
/// For the specified mime type find the decoder.
/// </summary>
/// <param name="format">The format to discover</param>
/// <returns>The <see cref="IImageDecoder"/> if found otherwise null</returns>
public IImageDecoder FindDecoder(IImageFormat format)
{
Guard.NotNull(format, nameof(format));
if (this.mimeTypeDecoders.TryGetValue(format, out IImageDecoder decoder))
{
return decoder;
}
return null;
}
/// <summary>
/// For the specified mime type find the encoder.
/// </summary>
/// <param name="format">The format to discover</param>
/// <returns>The <see cref="IImageEncoder"/> if found otherwise null</returns>
public IImageEncoder FindEncoder(IImageFormat format)
{
Guard.NotNull(format, nameof(format));
if (this.mimeTypeEncoders.TryGetValue(format, out IImageEncoder encoder))
{
return encoder;
}
return null;
}
/// <summary>
/// Creates the default instance with the following <see cref="IConfigurationModule"/>s preregistered:
/// <para><see cref="PngConfigurationModule"/></para>
/// <para><see cref="JpegConfigurationModule"/></para>
/// <para><see cref="GifConfigurationModule"/></para>
/// <para><see cref="BmpConfigurationModule"/></para>
/// </summary>
/// <returns>The default configuration of <see cref="Configuration"/></returns>
internal static Configuration CreateDefaultInstance()
{
return new Configuration(
new PngConfigurationModule(),
new JpegConfigurationModule(),
new GifConfigurationModule(),
new BmpConfigurationModule());
}
/// <summary>
/// Sets the max header size.
/// </summary>
private void SetMaxHeaderSize()
{
this.MaxHeaderSize = this.imageFormatDetectors.Max(x => x.HeaderSize);
}
}
}
// 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
{
/// <summary>
/// Provides initialization code which allows extending the library.
/// </summary>
public sealed class Configuration
{
/// <summary>
/// A lazily initialized configuration default instance.
/// </summary>
private static readonly Lazy<Configuration> Lazy = new Lazy<Configuration>(CreateDefaultInstance);
/// <summary>
/// Initializes a new instance of the <see cref="Configuration" /> class.
/// </summary>
public Configuration()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Configuration" /> class.
/// </summary>
/// <param name="configurationModules">A collection of configuration modules to register</param>
public Configuration(params IConfigurationModule[] configurationModules)
{
if (configurationModules != null)
{
foreach (IConfigurationModule p in configurationModules)
{
p.Configure(this);
}
}
}
/// <summary>
/// Gets the default <see cref="Configuration"/> instance.
/// </summary>
public static Configuration Default { get; } = Lazy.Value;
/// <summary>
/// Gets the global parallel options for processing tasks in parallel.
/// </summary>
public ParallelOptions ParallelOptions { get; private set; } = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount };
/// <summary>
/// Gets the currently registered <see cref="IImageFormat"/>s.
/// </summary>
public IEnumerable<IImageFormat> ImageFormats => this.ImageFormatsManager.ImageFormats;
/// <summary>
/// Gets or sets the position in a stream to use for reading when using a seekable stream as an image data source.
/// </summary>
public ReadOrigin ReadOrigin { get; set; } = ReadOrigin.Current;
/// <summary>
/// Gets or sets the <see cref="ImageFormatManager"/> that is currently in use.
/// </summary>
public ImageFormatManager ImageFormatsManager { get; set; } = new ImageFormatManager();
/// <summary>
/// Gets or sets the <see cref="MemoryManager"/> that is currently in use.
/// </summary>
public MemoryManager MemoryManager { get; set; } = ArrayPoolMemoryManager.CreateDefault();
/// <summary>
/// Gets the maximum header size of all the formats.
/// </summary>
internal int MaxHeaderSize => this.ImageFormatsManager.MaxHeaderSize;
#if !NETSTANDARD1_1
/// <summary>
/// Gets or sets the filesystem helper for accessing the local file system.
/// </summary>
internal IFileSystem FileSystem { get; set; } = new LocalFileSystem();
#endif
/// <summary>
/// Gets or sets the image operations provider factory.
/// </summary>
internal IImageProcessingContextFactory ImageOperationsProvider { get; set; } = new DefaultImageOperationsProviderFactory();
/// <summary>
/// Registers a new format provider.
/// </summary>
/// <param name="configuration">The configuration provider to call configure on.</param>
public void Configure(IConfigurationModule configuration)
{
Guard.NotNull(configuration, nameof(configuration));
configuration.Configure(this);
}
/// <summary>
/// Creates a shallow copy of the <see cref="Configuration"/>
/// </summary>
/// <returns>A new configuration instance</returns>
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
};
}
/// <summary>
/// Creates the default instance with the following <see cref="IConfigurationModule"/>s preregistered:
/// <para><see cref="PngConfigurationModule"/></para>
/// <para><see cref="JpegConfigurationModule"/></para>
/// <para><see cref="GifConfigurationModule"/></para>
/// <para><see cref="BmpConfigurationModule"/></para>
/// </summary>
/// <returns>The default configuration of <see cref="Configuration"/></returns>
internal static Configuration CreateDefaultInstance()
{
return new Configuration(
new PngConfigurationModule(),
new JpegConfigurationModule(),
new GifConfigurationModule(),
new BmpConfigurationModule());
}
}
}

6
src/ImageSharp/Formats/Bmp/BmpConfigurationModule.cs

@ -11,9 +11,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp
/// <inheritdoc/>
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());
}
}
}

2
src/ImageSharp/Formats/Bmp/ImageExtensions.cs

@ -36,6 +36,6 @@ namespace SixLabors.ImageSharp
/// <exception cref="System.ArgumentNullException">Thrown if the stream is null.</exception>
public static void SaveAsBmp<TPixel>(this Image<TPixel> source, Stream stream, BmpEncoder encoder)
where TPixel : struct, IPixel<TPixel>
=> source.Save(stream, encoder ?? source.GetConfiguration().FindEncoder(ImageFormats.Bmp));
=> source.Save(stream, encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(ImageFormats.Bmp));
}
}

6
src/ImageSharp/Formats/Gif/GifConfigurationModule.cs

@ -11,10 +11,10 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// <inheritdoc/>
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());
}
}
}

2
src/ImageSharp/Formats/Gif/ImageExtensions.cs

@ -36,6 +36,6 @@ namespace SixLabors.ImageSharp
/// <exception cref="System.ArgumentNullException">Thrown if the stream is null.</exception>
public static void SaveAsGif<TPixel>(this Image<TPixel> source, Stream stream, GifEncoder encoder)
where TPixel : struct, IPixel<TPixel>
=> source.Save(stream, encoder ?? source.GetConfiguration().FindEncoder(ImageFormats.Gif));
=> source.Save(stream, encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(ImageFormats.Gif));
}
}

2
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.
/// </summary>
internal struct PackedField : IEquatable<PackedField>
internal readonly struct PackedField : IEquatable<PackedField>
{
/// <summary>
/// The individual bits representing the packed byte.

186
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
{
/// <summary>
/// Collection of Image Formats to be used in <see cref="Configuration" /> class.
/// </summary>
public class ImageFormatManager
{
/// <summary>
/// The list of supported <see cref="IImageEncoder"/> keyed to mime types.
/// </summary>
private readonly ConcurrentDictionary<IImageFormat, IImageEncoder> mimeTypeEncoders = new ConcurrentDictionary<IImageFormat, IImageEncoder>();
/// <summary>
/// The list of supported <see cref="IImageEncoder"/> keyed to mime types.
/// </summary>
private readonly ConcurrentDictionary<IImageFormat, IImageDecoder> mimeTypeDecoders = new ConcurrentDictionary<IImageFormat, IImageDecoder>();
/// <summary>
/// The list of supported <see cref="IImageFormat"/>s.
/// </summary>
private readonly ConcurrentBag<IImageFormat> imageFormats = new ConcurrentBag<IImageFormat>();
/// <summary>
/// The list of supported <see cref="IImageFormatDetector"/>s.
/// </summary>
private ConcurrentBag<IImageFormatDetector> imageFormatDetectors = new ConcurrentBag<IImageFormatDetector>();
/// <summary>
/// Initializes a new instance of the <see cref="ImageFormatManager" /> class.
/// </summary>
public ImageFormatManager()
{
}
/// <summary>
/// Gets the maximum header size of all the formats.
/// </summary>
internal int MaxHeaderSize { get; private set; }
/// <summary>
/// Gets the currently registered <see cref="IImageFormat"/>s.
/// </summary>
public IEnumerable<IImageFormat> ImageFormats => this.imageFormats;
/// <summary>
/// Gets the currently registered <see cref="IImageFormatDetector"/>s.
/// </summary>
internal IEnumerable<IImageFormatDetector> FormatDetectors => this.imageFormatDetectors;
/// <summary>
/// Gets the currently registered <see cref="IImageDecoder"/>s.
/// </summary>
internal IEnumerable<KeyValuePair<IImageFormat, IImageDecoder>> ImageDecoders => this.mimeTypeDecoders;
/// <summary>
/// Gets the currently registered <see cref="IImageEncoder"/>s.
/// </summary>
internal IEnumerable<KeyValuePair<IImageFormat, IImageEncoder>> ImageEncoders => this.mimeTypeEncoders;
/// <summary>
/// Registers a new format provider.
/// </summary>
/// <param name="format">The format to register as a known format.</param>
public void AddImageFormat(IImageFormat format)
{
Guard.NotNull(format, nameof(format));
Guard.NotNull(format.MimeTypes, nameof(format.MimeTypes));
Guard.NotNull(format.FileExtensions, nameof(format.FileExtensions));
this.imageFormats.Add(format);
}
/// <summary>
/// For the specified file extensions type find the e <see cref="IImageFormat"/>.
/// </summary>
/// <param name="extension">The extension to discover</param>
/// <returns>The <see cref="IImageFormat"/> if found otherwise null</returns>
public IImageFormat FindFormatByFileExtension(string extension)
{
return this.imageFormats.FirstOrDefault(x => x.FileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase));
}
/// <summary>
/// For the specified mime type find the <see cref="IImageFormat"/>.
/// </summary>
/// <param name="mimeType">The mime-type to discover</param>
/// <returns>The <see cref="IImageFormat"/> if found; otherwise null</returns>
public IImageFormat FindFormatByMimeType(string mimeType)
{
return this.imageFormats.FirstOrDefault(x => x.MimeTypes.Contains(mimeType, StringComparer.OrdinalIgnoreCase));
}
/// <summary>
/// Sets a specific image encoder as the encoder for a specific image format.
/// </summary>
/// <param name="imageFormat">The image format to register the encoder for.</param>
/// <param name="encoder">The encoder to use,</param>
public void SetEncoder(IImageFormat imageFormat, IImageEncoder encoder)
{
Guard.NotNull(imageFormat, nameof(imageFormat));
Guard.NotNull(encoder, nameof(encoder));
this.AddImageFormat(imageFormat);
this.mimeTypeEncoders.AddOrUpdate(imageFormat, encoder, (s, e) => encoder);
}
/// <summary>
/// Sets a specific image decoder as the decoder for a specific image format.
/// </summary>
/// <param name="imageFormat">The image format to register the encoder for.</param>
/// <param name="decoder">The decoder to use,</param>
public void SetDecoder(IImageFormat imageFormat, IImageDecoder decoder)
{
Guard.NotNull(imageFormat, nameof(imageFormat));
Guard.NotNull(decoder, nameof(decoder));
this.AddImageFormat(imageFormat);
this.mimeTypeDecoders.AddOrUpdate(imageFormat, decoder, (s, e) => decoder);
}
/// <summary>
/// Removes all the registered image format detectors.
/// </summary>
public void ClearImageFormatDetectors()
{
this.imageFormatDetectors = new ConcurrentBag<IImageFormatDetector>();
}
/// <summary>
/// Adds a new detector for detecting mime types.
/// </summary>
/// <param name="detector">The detector to add</param>
public void AddImageFormatDetector(IImageFormatDetector detector)
{
Guard.NotNull(detector, nameof(detector));
this.imageFormatDetectors.Add(detector);
this.SetMaxHeaderSize();
}
/// <summary>
/// For the specified mime type find the decoder.
/// </summary>
/// <param name="format">The format to discover</param>
/// <returns>The <see cref="IImageDecoder"/> if found otherwise null</returns>
public IImageDecoder FindDecoder(IImageFormat format)
{
Guard.NotNull(format, nameof(format));
if (this.mimeTypeDecoders.TryGetValue(format, out IImageDecoder decoder))
{
return decoder;
}
return null;
}
/// <summary>
/// For the specified mime type find the encoder.
/// </summary>
/// <param name="format">The format to discover</param>
/// <returns>The <see cref="IImageEncoder"/> if found otherwise null</returns>
public IImageEncoder FindEncoder(IImageFormat format)
{
Guard.NotNull(format, nameof(format));
if (this.mimeTypeEncoders.TryGetValue(format, out IImageEncoder encoder))
{
return encoder;
}
return null;
}
/// <summary>
/// Sets the max header size.
/// </summary>
private void SetMaxHeaderSize()
{
this.MaxHeaderSize = this.imageFormatDetectors.Max(x => x.HeaderSize);
}
}
}

5
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<short> coefficients)
{
ref byte selfRef = ref Unsafe.As<Block8x8, byte>(ref this);
ref byte sourceRef = ref coefficients.NonPortableCast<short, byte>().DangerousGetPinnableReference();
ref byte sourceRef = ref MemoryMarshal.GetReference(coefficients.NonPortableCast<short, byte>());
Unsafe.CopyBlock(ref selfRef, ref sourceRef, Size * sizeof(short));
}
@ -204,7 +205,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
public void CopyTo(Span<short> destination)
{
ref byte selfRef = ref Unsafe.As<Block8x8, byte>(ref this);
ref byte destRef = ref destination.NonPortableCast<short, byte>().DangerousGetPinnableReference();
ref byte destRef = ref MemoryMarshal.GetReference(destination.NonPortableCast<short, byte>());
Unsafe.CopyBlock(ref destRef, ref selfRef, Size * sizeof(short));
}

4
src/ImageSharp/Formats/Jpeg/Common/Block8x8F.cs

@ -163,7 +163,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void LoadFrom(Span<float> source)
{
ref byte s = ref Unsafe.As<float, byte>(ref source.DangerousGetPinnableReference());
ref byte s = ref Unsafe.As<float, byte>(ref MemoryMarshal.GetReference(source));
ref byte d = ref Unsafe.As<Block8x8F, byte>(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<float> dest)
{
ref byte d = ref Unsafe.As<float, byte>(ref dest.DangerousGetPinnableReference());
ref byte d = ref Unsafe.As<float, byte>(ref MemoryMarshal.GetReference(dest));
ref byte s = ref Unsafe.As<Block8x8F, byte>(ref this);
Unsafe.CopyBlock(ref d, ref s, Size * sizeof(float));

2
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.
/// </summary>
/// <remarks>See the included 5116.DCT.pdf file in the source for more information.</remarks>
internal struct AdobeMarker : IEquatable<AdobeMarker>
internal readonly struct AdobeMarker : IEquatable<AdobeMarker>
{
/// <summary>
/// Gets the length of an adobe marker segment.

9
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<float, Vector4Pair>(ref values.Component0.DangerousGetPinnableReference());
ref Unsafe.As<float, Vector4Pair>(ref MemoryMarshal.GetReference(values.Component0));
ref Vector4Pair cbBase =
ref Unsafe.As<float, Vector4Pair>(ref values.Component1.DangerousGetPinnableReference());
ref Unsafe.As<float, Vector4Pair>(ref MemoryMarshal.GetReference(values.Component1));
ref Vector4Pair crBase =
ref Unsafe.As<float, Vector4Pair>(ref values.Component2.DangerousGetPinnableReference());
ref Unsafe.As<float, Vector4Pair>(ref MemoryMarshal.GetReference(values.Component2));
ref Vector4Octet resultBase =
ref Unsafe.As<Vector4, Vector4Octet>(ref result.DangerousGetPinnableReference());
ref Unsafe.As<Vector4, Vector4Octet>(ref MemoryMarshal.GetReference(result));
var chromaOffset = new Vector4(-128f);

9
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<float> yBase =
ref Unsafe.As<float, Vector<float>>(ref values.Component0.DangerousGetPinnableReference());
ref Unsafe.As<float, Vector<float>>(ref MemoryMarshal.GetReference(values.Component0));
ref Vector<float> cbBase =
ref Unsafe.As<float, Vector<float>>(ref values.Component1.DangerousGetPinnableReference());
ref Unsafe.As<float, Vector<float>>(ref MemoryMarshal.GetReference(values.Component1));
ref Vector<float> crBase =
ref Unsafe.As<float, Vector<float>>(ref values.Component2.DangerousGetPinnableReference());
ref Unsafe.As<float, Vector<float>>(ref MemoryMarshal.GetReference(values.Component2));
ref Vector4Octet resultBase =
ref Unsafe.As<Vector4, Vector4Octet>(ref result.DangerousGetPinnableReference());
ref Unsafe.As<Vector4, Vector4Octet>(ref MemoryMarshal.GetReference(result));
var chromaOffset = new Vector<float>(-128f);

4
src/ImageSharp/Formats/Jpeg/Common/Decoder/ColorConverters/JpegColorConverter.cs

@ -66,7 +66,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder.ColorConverters
/// <summary>
/// A stack-only struct to reference the input buffers using <see cref="ReadOnlySpan{T}"/>-s.
/// </summary>
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
{
/// <summary>
/// The component count

2
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?
/// </summary>
internal struct JFifMarker : IEquatable<JFifMarker>
internal readonly struct JFifMarker : IEquatable<JFifMarker>
{
/// <summary>
/// Gets the length of an JFIF marker segment.

2
src/ImageSharp/Formats/Jpeg/Common/GenericBlock8x8.cs

@ -85,7 +85,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
ref byte blockStart = ref Unsafe.As<GenericBlock8x8<T>, byte>(ref this);
ref byte imageStart = ref Unsafe.As<T, byte>(
ref Unsafe.Add(ref source.GetRowSpan(sourceY).DangerousGetPinnableReference(), sourceX));
ref Unsafe.Add(ref MemoryMarshal.GetReference(source.GetRowSpan(sourceY)), sourceX));
int blockRowSizeInBytes = 8 * Unsafe.SizeOf<T>();
int imageRowSizeInBytes = source.Width * Unsafe.SizeOf<T>();

10
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
{
/// <summary>
@ -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;
}
/// <summary>
/// Reset the Huffman decoder.
/// </summary>
public void ResetHuffmanDecoder()
{
this.Bits = default(Bits);
}
}
}

181
src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigJpegScanDecoder.cs

@ -94,6 +94,21 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
/// </summary>
private int eobRun;
/// <summary>
/// The block counter
/// </summary>
private int blockCounter;
/// <summary>
/// The MCU counter
/// </summary>
private int mcuCounter;
/// <summary>
/// The expected RST marker value
/// </summary>
private byte expectedRst;
/// <summary>
/// Initializes a default-constructed <see cref="OrigJpegScanDecoder"/> instance for reading data from <see cref="OrigJpegDecoderCore"/>-s stream.
/// </summary>
@ -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;
}
/// <summary>
/// Reset the DC components, as per section F.2.1.3.1.
/// </summary>
private void ResetDcValues()
{
Unsafe.InitBlock(this.pointers.Dc, default(byte), sizeof(int) * OrigJpegDecoderCore.MaxComponents);
}

2
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.
/// </summary>
internal struct HuffmanLut
internal readonly struct HuffmanLut
{
/// <summary>
/// The compiled representations of theHuffmanSpec.

2
src/ImageSharp/Formats/Jpeg/GolangPort/Components/Encoder/HuffmanSpec.cs

@ -6,7 +6,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Encoder
/// <summary>
/// The Huffman encoding specifications.
/// </summary>
internal struct HuffmanSpec
internal readonly struct HuffmanSpec
{
#pragma warning disable SA1118 // ParameterMustNotSpanMultipleLines

9
src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs

@ -411,6 +411,15 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
this.InitDerivedMetaDataProperties();
}
/// <summary>
/// Returns true if 'mcuCounter' is at restart interval
/// </summary>
public bool IsAtRestartInterval(int mcuCounter)
{
return this.RestartInterval > 0 && mcuCounter % this.RestartInterval == 0
&& mcuCounter < this.TotalMCUCount;
}
/// <summary>
/// Assigns derived metadata properties to <see cref="MetaData"/>, eg. horizontal and vertical resolution if it has a JFIF header.
/// </summary>

2
src/ImageSharp/Formats/Jpeg/ImageExtensions.cs

@ -36,6 +36,6 @@ namespace SixLabors.ImageSharp
/// <exception cref="System.ArgumentNullException">Thrown if the stream is null.</exception>
public static void SaveAsJpeg<TPixel>(this Image<TPixel> source, Stream stream, JpegEncoder encoder)
where TPixel : struct, IPixel<TPixel>
=> source.Save(stream, encoder ?? source.GetConfiguration().FindEncoder(ImageFormats.Jpeg));
=> source.Save(stream, encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(ImageFormats.Jpeg));
}
}

6
src/ImageSharp/Formats/Jpeg/JpegConfigurationModule.cs

@ -11,10 +11,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
/// <inheritdoc/>
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());
}
}
}

2
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;

2
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.
/// </summary>
internal struct PdfJsYCbCrToRgbTables
internal readonly struct PdfJsYCbCrToRgbTables
{
/// <summary>
/// The red red-chrominance table

2
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));

11
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)

11
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))

7
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<byte> 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)

11
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)

2
src/ImageSharp/Formats/Png/ImageExtensions.cs

@ -35,6 +35,6 @@ namespace SixLabors.ImageSharp
/// <exception cref="System.ArgumentNullException">Thrown if the stream is null.</exception>
public static void SaveAsPng<TPixel>(this Image<TPixel> source, Stream stream, PngEncoder encoder)
where TPixel : struct, IPixel<TPixel>
=> source.Save(stream, encoder ?? source.GetConfiguration().FindEncoder(ImageFormats.Png));
=> source.Save(stream, encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(ImageFormats.Png));
}
}

6
src/ImageSharp/Formats/Png/PngConfigurationModule.cs

@ -11,9 +11,9 @@ namespace SixLabors.ImageSharp.Formats.Png
/// <inheritdoc/>
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());
}
}
}

4
src/ImageSharp/Formats/Png/PngDecoderCore.cs

@ -701,7 +701,7 @@ namespace SixLabors.ImageSharp.Formats.Png
Span<TPixel> rowSpan = pixels.GetPixelRowSpan(this.currentRow);
// Trim the first marker byte from the buffer
var scanlineBuffer = new Span<byte>(defilteredScanline, 1);
var scanlineBuffer = new Span<byte>(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<byte>(defilteredScanline, 1);
var scanlineBuffer = new Span<byte>(defilteredScanline, 1, defilteredScanline.Length - 1);
switch (this.pngColorType)
{

4
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;

2
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<IImageFormat, IImageDecoder> val in config.ImageDecoders)
foreach (KeyValuePair<IImageFormat, IImageDecoder> val in config.ImageFormatsManager.ImageDecoders)
{
stringBuilder.AppendLine($" - {val.Key.Name} : {val.Value.GetType().Name}");
}

10
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<IImageFormat, IImageEncoder> enc in source.GetConfiguration().ImageEncoders)
foreach (KeyValuePair<IImageFormat, IImageEncoder> 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<TPixel>
{
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<IImageFormat, IImageEncoder> val in source.GetConfiguration().ImageEncoders)
foreach (KeyValuePair<IImageFormat, IImageEncoder> val in source.GetConfiguration().ImageFormatsManager.ImageEncoders)
{
stringBuilder.AppendLine($" - {val.Key.Name} : {val.Value.GetType().Name}");
}

6
src/ImageSharp/ImageSharp.csproj

@ -29,6 +29,7 @@
<DebugType Condition="$(codecov) == ''">portable</DebugType>
<DebugSymbols>True</DebugSymbols>
<Features>IOperation</Features>
<LangVersion>7.2</LangVersion>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\Shared\*.cs" Exclude="bin\**;obj\**;**\*.xproj;packages\**" />
@ -40,12 +41,11 @@
<PrivateAssets>All</PrivateAssets>
</PackageReference>
<PackageReference Include="System.Buffers" Version="4.4.0" />
<PackageReference Include="System.Memory" Version="4.4.0-preview2-25405-01" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.4.0" />
<PackageReference Include="System.Memory" Version="4.5.0-preview1-26216-02" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.5.0-preview1-26216-02" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.1' OR '$(TargetFramework)' == 'netstandard1.3'">
<PackageReference Include="System.IO.Compression" Version="4.3.0" />
<PackageReference Include="System.Numerics.Vectors" Version="4.4.0" />
<PackageReference Include="System.Threading.Tasks.Parallel" Version="4.3.0" />
<PackageReference Include="System.ValueTuple" Version="4.4.0" />
</ItemGroup>

2
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.
/// </summary>
/// <typeparam name="T">The element type</typeparam>
internal struct BufferArea<T>
internal readonly struct BufferArea<T>
where T : struct
{
/// <summary>

3
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<T>(this IBuffer<T> buffer)
where T : struct =>
ref buffer.Span.DangerousGetPinnableReference();
ref MemoryMarshal.GetReference(buffer.Span);
public static void Read(this Stream stream, IManagedByteBuffer buffer)
{

7
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<T> FetchVector<T>(this Span<T> span)
where T : struct
{
return ref Unsafe.As<T, Vector<T>>(ref span.DangerousGetPinnableReference());
return ref Unsafe.As<T, Vector<T>>(ref MemoryMarshal.GetReference(span));
}
/// <summary>
@ -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<T, byte>(ref source.DangerousGetPinnableReference());
ref byte destRef = ref Unsafe.As<T, byte>(ref destination.DangerousGetPinnableReference());
ref byte srcRef = ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(source));
ref byte destRef = ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(destination));
int byteCount = Unsafe.SizeOf<T>() * count;

2
src/ImageSharp/MetaData/Profiles/ICC/Various/IccColorantTableEntry.cs

@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <summary>
/// Entry of ICC colorant table
/// </summary>
internal struct IccColorantTableEntry : IEquatable<IccColorantTableEntry>
internal readonly struct IccColorantTableEntry : IEquatable<IccColorantTableEntry>
{
/// <summary>
/// Initializes a new instance of the <see cref="IccColorantTableEntry"/> struct.

2
src/ImageSharp/MetaData/Profiles/ICC/Various/IccNamedColor.cs

@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <summary>
/// A specific color with a name
/// </summary>
internal struct IccNamedColor : IEquatable<IccNamedColor>
internal readonly struct IccNamedColor : IEquatable<IccNamedColor>
{
/// <summary>
/// Initializes a new instance of the <see cref="IccNamedColor"/> struct.

2
src/ImageSharp/MetaData/Profiles/ICC/Various/IccPositionNumber.cs

@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <summary>
/// Position of an object within an ICC profile
/// </summary>
internal struct IccPositionNumber : IEquatable<IccPositionNumber>
internal readonly struct IccPositionNumber : IEquatable<IccPositionNumber>
{
/// <summary>
/// Initializes a new instance of the <see cref="IccPositionNumber"/> struct.

2
src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileId.cs

@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <summary>
/// ICC Profile ID
/// </summary>
public struct IccProfileId : IEquatable<IccProfileId>
public readonly struct IccProfileId : IEquatable<IccProfileId>
{
/// <summary>
/// A profile ID with all values set to zero

2
src/ImageSharp/MetaData/Profiles/ICC/Various/IccResponseNumber.cs

@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <summary>
/// Associates a normalized device code with a measurement value
/// </summary>
internal struct IccResponseNumber : IEquatable<IccResponseNumber>
internal readonly struct IccResponseNumber : IEquatable<IccResponseNumber>
{
/// <summary>
/// Initializes a new instance of the <see cref="IccResponseNumber"/> struct.

2
src/ImageSharp/MetaData/Profiles/ICC/Various/IccScreeningChannel.cs

@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <summary>
/// A single channel of a <see cref="IccScreeningTagDataEntry"/>
/// </summary>
internal struct IccScreeningChannel : IEquatable<IccScreeningChannel>
internal readonly struct IccScreeningChannel : IEquatable<IccScreeningChannel>
{
/// <summary>
/// Initializes a new instance of the <see cref="IccScreeningChannel"/> struct.

2
src/ImageSharp/MetaData/Profiles/ICC/Various/IccTagTableEntry.cs

@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <summary>
/// Entry of ICC tag table
/// </summary>
internal struct IccTagTableEntry : IEquatable<IccTagTableEntry>
internal readonly struct IccTagTableEntry : IEquatable<IccTagTableEntry>
{
/// <summary>
/// Initializes a new instance of the <see cref="IccTagTableEntry"/> struct.

2
src/ImageSharp/Numerics/ValueSize.cs

@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp
/// <summary>
/// Represents a value in relation to a value on the image
/// </summary>
internal struct ValueSize : IEquatable<ValueSize>
internal readonly struct ValueSize : IEquatable<ValueSize>
{
/// <summary>
/// Initializes a new instance of the <see cref="ValueSize"/> struct.

35
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<TPixel>
{
@ -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++)
{

12
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<TPixel>
{
<#

28
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;
/// <content>
/// Provides optimized overrides for bulk operations.
/// </content>
@ -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++)
{

12
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;
/// <content>
/// Provides optimized overrides for bulk operations.
/// </content>

9
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++)
{

4
src/ImageSharp/PixelFormats/Rgba32.PixelOperations.cs

@ -57,8 +57,8 @@ namespace SixLabors.ImageSharp
int unpackedRawCount = count * 4;
ref uint sourceBase = ref Unsafe.As<Rgba32, uint>(ref sourceColors.DangerousGetPinnableReference());
ref UnpackedRGBA destBaseAsUnpacked = ref Unsafe.As<Vector4, UnpackedRGBA>(ref destVectors.DangerousGetPinnableReference());
ref uint sourceBase = ref Unsafe.As<Rgba32, uint>(ref MemoryMarshal.GetReference(sourceColors));
ref UnpackedRGBA destBaseAsUnpacked = ref Unsafe.As<Vector4, UnpackedRGBA>(ref MemoryMarshal.GetReference(destVectors));
ref Vector<uint> destBaseAsUInt = ref Unsafe.As<UnpackedRGBA, Vector<uint>>(ref destBaseAsUnpacked);
ref Vector<float> destBaseAsFloat = ref Unsafe.As<UnpackedRGBA, Vector<float>>(ref destBaseAsUnpacked);

2
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.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
internal struct PixelPair<TPixel> : IEquatable<PixelPair<TPixel>>
internal readonly struct PixelPair<TPixel> : IEquatable<PixelPair<TPixel>>
where TPixel : struct, IPixel<TPixel>
{
/// <summary>

6
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;

6
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++)
{

5
tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj

@ -23,7 +23,12 @@
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)'=='net461'">
<PackageReference Include="System.Numerics.Vectors" Version="4.4.0" />
<PackageReference Include="Colourful" Version="1.1.2" />
<PackageReference Include="System.Drawing.Common" Version="4.5.0-preview1-26216-02" />
<PackageReference Include="System.Memory" Version="4.5.0-preview1-26216-02" />
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0-preview1-26216-02" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\ImageSharp.Drawing\ImageSharp.Drawing.csproj" />
<ProjectReference Include="..\..\src\ImageSharp\ImageSharp.csproj" />

89
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<LocalFileSystem>(this.DefaultConfiguration.FileSystem);
Assert.IsType<LocalFileSystem>(this.ConfigurationEmpty.FileSystem);
}
[Fact]
public void IfAutoloadWellknwonFormatesIsTrueAllFormateAreLoaded()
{
Assert.Equal(4, this.DefaultConfiguration.ImageEncoders.Count());
Assert.Equal(4, this.DefaultConfiguration.ImageDecoders.Count());
}
}
/// <summary>
/// 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<ArgumentNullException>(() =>
{
this.DefaultConfiguration.AddImageFormatDetector(null);
});
}
[Fact]
public void RegisterNullMimeTypeEncoder()
{
Assert.Throws<ArgumentNullException>(() =>
{
this.DefaultConfiguration.SetEncoder(null, new Mock<IImageEncoder>().Object);
});
Assert.Throws<ArgumentNullException>(() =>
{
this.DefaultConfiguration.SetEncoder(ImageFormats.Bmp, null);
});
Assert.Throws<ArgumentNullException>(() =>
{
this.DefaultConfiguration.SetEncoder(null, null);
});
}
[Fact]
public void RegisterNullSetDecoder()
{
Assert.Throws<ArgumentNullException>(() =>
{
this.DefaultConfiguration.SetDecoder(null, new Mock<IImageDecoder>().Object);
});
Assert.Throws<ArgumentNullException>(() =>
{
this.DefaultConfiguration.SetDecoder(ImageFormats.Bmp, null);
});
Assert.Throws<ArgumentNullException>(() =>
{
this.DefaultConfiguration.SetDecoder(null, null);
});
}
[Fact]
public void RegisterMimeTypeEncoderReplacesLast()
{
IImageEncoder encoder1 = new Mock<IImageEncoder>().Object;
this.ConfigurationEmpty.SetEncoder(TestFormat.GlobalTestFormat, encoder1);
IImageEncoder found = this.ConfigurationEmpty.FindEncoder(TestFormat.GlobalTestFormat);
Assert.Equal(encoder1, found);
IImageEncoder encoder2 = new Mock<IImageEncoder>().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<IImageDecoder>().Object;
this.ConfigurationEmpty.SetDecoder(TestFormat.GlobalTestFormat, decoder1);
IImageDecoder found = this.ConfigurationEmpty.FindDecoder(TestFormat.GlobalTestFormat);
Assert.Equal(decoder1, found);
IImageDecoder decoder2 = new Mock<IImageDecoder>().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()
{

129
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<PngEncoder>().Count());
Assert.Equal(1, this.DefaultFormatsManager.ImageEncoders.Select(item => item.Value).OfType<BmpEncoder>().Count());
Assert.Equal(1, this.DefaultFormatsManager.ImageEncoders.Select(item => item.Value).OfType<JpegEncoder>().Count());
Assert.Equal(1, this.DefaultFormatsManager.ImageEncoders.Select(item => item.Value).OfType<GifEncoder>().Count());
Assert.Equal(1, this.DefaultFormatsManager.ImageDecoders.Select(item => item.Value).OfType<PngDecoder>().Count());
Assert.Equal(1, this.DefaultFormatsManager.ImageDecoders.Select(item => item.Value).OfType<BmpDecoder>().Count());
Assert.Equal(1, this.DefaultFormatsManager.ImageDecoders.Select(item => item.Value).OfType<JpegDecoder>().Count());
Assert.Equal(1, this.DefaultFormatsManager.ImageDecoders.Select(item => item.Value).OfType<BmpDecoder>().Count());
}
[Fact]
public void AddImageFormatDetectorNullthrows()
{
Assert.Throws<ArgumentNullException>(() =>
{
this.DefaultFormatsManager.AddImageFormatDetector(null);
});
}
[Fact]
public void RegisterNullMimeTypeEncoder()
{
Assert.Throws<ArgumentNullException>(() =>
{
this.DefaultFormatsManager.SetEncoder(null, new Mock<IImageEncoder>().Object);
});
Assert.Throws<ArgumentNullException>(() =>
{
this.DefaultFormatsManager.SetEncoder(ImageFormats.Bmp, null);
});
Assert.Throws<ArgumentNullException>(() =>
{
this.DefaultFormatsManager.SetEncoder(null, null);
});
}
[Fact]
public void RegisterNullSetDecoder()
{
Assert.Throws<ArgumentNullException>(() =>
{
this.DefaultFormatsManager.SetDecoder(null, new Mock<IImageDecoder>().Object);
});
Assert.Throws<ArgumentNullException>(() =>
{
this.DefaultFormatsManager.SetDecoder(ImageFormats.Bmp, null);
});
Assert.Throws<ArgumentNullException>(() =>
{
this.DefaultFormatsManager.SetDecoder(null, null);
});
}
[Fact]
public void RegisterMimeTypeEncoderReplacesLast()
{
IImageEncoder encoder1 = new Mock<IImageEncoder>().Object;
this.FormatsManagerEmpty.SetEncoder(TestFormat.GlobalTestFormat, encoder1);
IImageEncoder found = this.FormatsManagerEmpty.FindEncoder(TestFormat.GlobalTestFormat);
Assert.Equal(encoder1, found);
IImageEncoder encoder2 = new Mock<IImageEncoder>().Object;
this.FormatsManagerEmpty.SetEncoder(TestFormat.GlobalTestFormat, encoder2);
IImageEncoder found2 = this.FormatsManagerEmpty.FindEncoder(TestFormat.GlobalTestFormat);
Assert.Equal(encoder2, found2);
Assert.NotEqual(found, found2);
}
[Fact]
public void RegisterMimeTypeDecoderReplacesLast()
{
IImageDecoder decoder1 = new Mock<IImageDecoder>().Object;
this.FormatsManagerEmpty.SetDecoder(TestFormat.GlobalTestFormat, decoder1);
IImageDecoder found = this.FormatsManagerEmpty.FindDecoder(TestFormat.GlobalTestFormat);
Assert.Equal(decoder1, found);
IImageDecoder decoder2 = new Mock<IImageDecoder>().Object;
this.FormatsManagerEmpty.SetDecoder(TestFormat.GlobalTestFormat, decoder2);
IImageDecoder found2 = this.FormatsManagerEmpty.FindDecoder(TestFormat.GlobalTestFormat);
Assert.Equal(decoder2, found2);
Assert.NotEqual(found, found2);
}
[Fact]
public void AddFormatCallsConfig()
{
var provider = new Mock<IConfigurationModule>();
var config = new Configuration();
config.Configure(provider.Object);
provider.Verify(x => x.Configure(config));
}
}
}

6
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)]

2
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();

4
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();

4
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<Rgba32>(config, 1, 1);
}

3
tests/ImageSharp.Tests/ImageSharp.Tests.csproj

@ -16,7 +16,8 @@
<None Include="PixelFormats\PixelOperationsTests.Blender.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="System.Drawing.Common" Version="4.5.0-preview2-26202-05" />
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0-preview1-26216-02" />
<PackageReference Include="System.Drawing.Common" Version="4.5.0-preview1-26216-02" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
<PackageReference Include="Moq" Version="4.7.145" />

2
tests/ImageSharp.Tests/Memory/ArrayPoolMemoryManagerTests.cs

@ -133,7 +133,7 @@ namespace SixLabors.ImageSharp.Tests.Memory
public void ReleaseRetainedResources_ReplacesInnerArrayPool(bool keepBufferAlive)
{
IBuffer<int> buffer = this.MemoryManager.Allocate<int>(32);
ref int ptrToPrev0 = ref buffer.Span.DangerousGetPinnableReference();
ref int ptrToPrev0 = ref MemoryMarshal.GetReference(buffer.Span);
if (!keepBufferAlive)
{

4
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<T>(Span<T> span, IBuffer<T> 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");

7
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<T> buffer = this.Allocate<T>(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));

20
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<TestStructs.Foo>(source, 1);
var apDest = new Span<TestStructs.Foo>(dest, 1);
var apSource = new Span<TestStructs.Foo>(source, 1, source.Length - 1);
var apDest = new Span<TestStructs.Foo>(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<TestStructs.AlignedFoo>(source, 1);
var apDest = new Span<TestStructs.AlignedFoo>(dest, 1);
var apSource = new Span<TestStructs.AlignedFoo>(source, 1, source.Length - 1);
var apDest = new Span<TestStructs.AlignedFoo>(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<int>(source, 1);
var apDest = new Span<int>(dest, 1);
var apSource = new Span<int>(source, 1, source.Length - 1);
var apDest = new Span<int>(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<TestStructs.Foo>(source, 1);
var apDest = new Span<byte>(dest, sizeof(TestStructs.Foo));
var apSource = new Span<TestStructs.Foo>(source, 1, source.Length - 1);
var apDest = new Span<byte>(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<TestStructs.AlignedFoo>(source, 1);
var apDest = new Span<byte>(dest, sizeof(TestStructs.AlignedFoo));
var apSource = new Span<TestStructs.AlignedFoo>(source, 1, source.Length - 1);
var apDest = new Span<byte>(dest, sizeof(TestStructs.AlignedFoo), dest.Length - sizeof(TestStructs.AlignedFoo));
SpanHelper.Copy(apSource.AsBytes(), apDest, (count - 1) * sizeof(TestStructs.AlignedFoo));

6
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

1
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";

12
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()

2
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())
//{

2
tests/Images/External

@ -1 +1 @@
Subproject commit 8714b94dc4bab6788fcbb6254174db2b9c8f69c9
Subproject commit 653f0c7e3c84657f68dd46e5a380186b3696b956

BIN
tests/Images/Input/Jpg/baseline/badrst.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Loading…
Cancel
Save