diff --git a/src/ImageSharp/Bootstrapper.cs b/src/ImageSharp/Bootstrapper.cs
index de4bcc938..a73205a76 100644
--- a/src/ImageSharp/Bootstrapper.cs
+++ b/src/ImageSharp/Bootstrapper.cs
@@ -19,16 +19,25 @@ namespace ImageSharp
public class Bootstrapper
{
///
- /// A new instance Initializes a new instance of the class.
- /// with lazy initialization.
+ /// A singleton of the class.
///
- private static readonly Lazy Lazy = new Lazy(() => new Bootstrapper());
+ private static readonly Bootstrapper Instance = new Bootstrapper();
///
- /// The default list of supported
+ /// The list of supported .
///
private readonly List imageFormats;
+ ///
+ /// The parallel options for processing tasks in parallel.
+ ///
+ private readonly ParallelOptions parallelOptions;
+
+ ///
+ /// An object that can be used to synchronize access to the .
+ ///
+ private readonly object syncRoot = new object();
+
///
/// Prevents a default instance of the class from being created.
///
@@ -41,28 +50,24 @@ namespace ImageSharp
new PngFormat(),
new GifFormat()
};
+ this.parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount };
}
- ///
- /// Gets the current bootstrapper instance.
- ///
- public static Bootstrapper Instance => Lazy.Value;
-
///
/// Gets the collection of supported
///
- public IReadOnlyCollection ImageFormats => new ReadOnlyCollection(this.imageFormats);
+ public static IReadOnlyCollection ImageFormats => new ReadOnlyCollection(Instance.imageFormats);
///
- /// Gets or sets the global parallel options for processing tasks in parallel.
+ /// Gets the global parallel options for processing tasks in parallel.
///
- public ParallelOptions ParallelOptions { get; set; } = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount };
+ public static ParallelOptions ParallelOptions => Instance.parallelOptions;
///
/// Adds a new to the collection of supported image formats.
///
/// The new format to add.
- public void AddImageFormat(IImageFormat format)
+ public static void AddImageFormat(IImageFormat format)
{
Guard.NotNull(format, nameof(format));
Guard.NotNull(format.Encoder, nameof(format), "The encoder should not be null.");
@@ -71,9 +76,17 @@ namespace ImageSharp
Guard.NotNullOrEmpty(format.Extension, nameof(format), "The extension should not be null or empty.");
Guard.NotNullOrEmpty(format.SupportedExtensions, nameof(format), "The supported extensions not be null or empty.");
- GuardDuplicate(format);
+ Instance.AddImageFormatLocked(format);
+ }
- this.imageFormats.Add(format);
+ private void AddImageFormatLocked(IImageFormat format)
+ {
+ lock (this.syncRoot)
+ {
+ this.GuardDuplicate(format);
+
+ this.imageFormats.Add(format);
+ }
}
private void GuardDuplicate(IImageFormat format)
diff --git a/src/ImageSharp/Formats/Jpg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpg/JpegDecoderCore.cs
index c209cde3f..66882e492 100644
--- a/src/ImageSharp/Formats/Jpg/JpegDecoderCore.cs
+++ b/src/ImageSharp/Formats/Jpg/JpegDecoderCore.cs
@@ -1286,7 +1286,7 @@ namespace ImageSharp.Formats
Parallel.For(
0,
height,
- Bootstrapper.Instance.ParallelOptions,
+ Bootstrapper.ParallelOptions,
y =>
{
int yoff = this.grayImage.GetRowOffset(y);
@@ -1324,7 +1324,7 @@ namespace ImageSharp.Formats
Parallel.For(
0,
height,
- Bootstrapper.Instance.ParallelOptions,
+ Bootstrapper.ParallelOptions,
y =>
{
int yo = this.ycbcrImage.GetRowYOffset(y);
@@ -1366,7 +1366,7 @@ namespace ImageSharp.Formats
Parallel.For(
0,
height,
- Bootstrapper.Instance.ParallelOptions,
+ Bootstrapper.ParallelOptions,
y =>
{
int yo = this.ycbcrImage.GetRowYOffset(y);
diff --git a/src/ImageSharp/Image/Image.cs b/src/ImageSharp/Image/Image.cs
index 1b9b27338..d9ad0078a 100644
--- a/src/ImageSharp/Image/Image.cs
+++ b/src/ImageSharp/Image/Image.cs
@@ -43,7 +43,7 @@ namespace ImageSharp
///
public Image()
{
- this.CurrentImageFormat = Bootstrapper.Instance.ImageFormats.First(f => f.GetType() == typeof(PngFormat));
+ this.CurrentImageFormat = Bootstrapper.ImageFormats.First(f => f.GetType() == typeof(PngFormat));
}
///
@@ -55,7 +55,7 @@ namespace ImageSharp
public Image(int width, int height)
: base(width, height)
{
- this.CurrentImageFormat = Bootstrapper.Instance.ImageFormats.First(f => f.GetType() == typeof(PngFormat));
+ this.CurrentImageFormat = Bootstrapper.ImageFormats.First(f => f.GetType() == typeof(PngFormat));
}
///
@@ -91,11 +91,6 @@ namespace ImageSharp
this.CopyProperties(other);
}
- ///
- /// Gets a list of supported image formats.
- ///
- public IReadOnlyCollection Formats { get; } = Bootstrapper.Instance.ImageFormats;
-
///
/// Gets or sets the resolution of the image in x- direction. It is defined as
/// number of dots per inch and should be an positive value.
@@ -288,7 +283,7 @@ namespace ImageSharp
Parallel.For(
0,
target.Height,
- Bootstrapper.Instance.ParallelOptions,
+ Bootstrapper.ParallelOptions,
y =>
{
for (int x = 0; x < target.Width; x++)
@@ -352,7 +347,7 @@ namespace ImageSharp
///
private void Load(Stream stream)
{
- if (!this.Formats.Any())
+ if (!Bootstrapper.ImageFormats.Any())
{
return;
}
@@ -387,7 +382,7 @@ namespace ImageSharp
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.AppendLine("Image cannot be loaded. Available formats:");
- foreach (IImageFormat format in this.Formats)
+ foreach (IImageFormat format in Bootstrapper.ImageFormats)
{
stringBuilder.AppendLine("-" + format);
}
@@ -404,7 +399,7 @@ namespace ImageSharp
///
private bool Decode(Stream stream)
{
- int maxHeaderSize = this.Formats.Max(x => x.Decoder.HeaderSize);
+ int maxHeaderSize = Bootstrapper.ImageFormats.Max(x => x.Decoder.HeaderSize);
if (maxHeaderSize > 0)
{
byte[] header = new byte[maxHeaderSize];
@@ -413,7 +408,7 @@ namespace ImageSharp
stream.Read(header, 0, maxHeaderSize);
stream.Position = 0;
- IImageFormat format = this.Formats.FirstOrDefault(x => x.Decoder.IsSupportedFileFormat(header));
+ IImageFormat format = Bootstrapper.ImageFormats.FirstOrDefault(x => x.Decoder.IsSupportedFileFormat(header));
if (format != null)
{
format.Decoder.Decode(this, stream);
diff --git a/src/ImageSharp/Image/ImageFrame.cs b/src/ImageSharp/Image/ImageFrame.cs
index 5e9c9fb9b..dff5d1746 100644
--- a/src/ImageSharp/Image/ImageFrame.cs
+++ b/src/ImageSharp/Image/ImageFrame.cs
@@ -67,7 +67,7 @@ namespace ImageSharp
Parallel.For(
0,
target.Height,
- Bootstrapper.Instance.ParallelOptions,
+ Bootstrapper.ParallelOptions,
y =>
{
for (int x = 0; x < target.Width; x++)
diff --git a/src/ImageSharp/ImageProcessor.cs b/src/ImageSharp/ImageProcessor.cs
index 3da7496fe..4b92eb5d1 100644
--- a/src/ImageSharp/ImageProcessor.cs
+++ b/src/ImageSharp/ImageProcessor.cs
@@ -18,7 +18,7 @@ namespace ImageSharp.Processors
where TPacked : struct, IEquatable
{
///
- public virtual ParallelOptions ParallelOptions { get; set; } = Bootstrapper.Instance.ParallelOptions;
+ public virtual ParallelOptions ParallelOptions { get; set; } = Bootstrapper.ParallelOptions;
///
public virtual bool Compand { get; set; } = false;
diff --git a/src/ImageSharp/Quantizers/QuantizedImage.cs b/src/ImageSharp/Quantizers/QuantizedImage.cs
index 600d8aa8f..2f690012a 100644
--- a/src/ImageSharp/Quantizers/QuantizedImage.cs
+++ b/src/ImageSharp/Quantizers/QuantizedImage.cs
@@ -79,7 +79,7 @@ namespace ImageSharp.Quantizers
Parallel.For(
0,
pixelCount,
- Bootstrapper.Instance.ParallelOptions,
+ Bootstrapper.ParallelOptions,
i =>
{
TColor color = this.Palette[Math.Min(palletCount, this.Pixels[i])];
diff --git a/src/ImageSharp/Quantizers/Wu/WuQuantizer.cs b/src/ImageSharp/Quantizers/Wu/WuQuantizer.cs
index 2542537c7..6eef9633c 100644
--- a/src/ImageSharp/Quantizers/Wu/WuQuantizer.cs
+++ b/src/ImageSharp/Quantizers/Wu/WuQuantizer.cs
@@ -749,7 +749,7 @@ namespace ImageSharp.Quantizers
Parallel.For(
0,
height,
- Bootstrapper.Instance.ParallelOptions,
+ Bootstrapper.ParallelOptions,
y =>
{
byte[] rgba = ArrayPool.Shared.Rent(4);
diff --git a/tests/ImageSharp.Benchmarks/Image/CopyPixels.cs b/tests/ImageSharp.Benchmarks/Image/CopyPixels.cs
index c70259db6..59f006b46 100644
--- a/tests/ImageSharp.Benchmarks/Image/CopyPixels.cs
+++ b/tests/ImageSharp.Benchmarks/Image/CopyPixels.cs
@@ -25,7 +25,7 @@ namespace ImageSharp.Benchmarks.Image
Parallel.For(
0,
source.Height,
- Bootstrapper.Instance.ParallelOptions,
+ Bootstrapper.ParallelOptions,
y =>
{
for (int x = 0; x < source.Width; x++)
@@ -49,7 +49,7 @@ namespace ImageSharp.Benchmarks.Image
Parallel.For(
0,
source.Height,
- Bootstrapper.Instance.ParallelOptions,
+ Bootstrapper.ParallelOptions,
y =>
{
sourcePixels.CopyBlock(0, y, targetPixels, 0, y, source.Width);
diff --git a/tests/ImageSharp.Tests/BootstrapperTests.cs b/tests/ImageSharp.Tests/BootstrapperTests.cs
index 4c8ca7f8f..df93f99c9 100644
--- a/tests/ImageSharp.Tests/BootstrapperTests.cs
+++ b/tests/ImageSharp.Tests/BootstrapperTests.cs
@@ -48,7 +48,7 @@ namespace ImageSharp.Tests
exception = Assert.Throws(() =>
{
- Bootstrapper.Instance.AddImageFormat(null);
+ Bootstrapper.AddImageFormat(null);
});
var format = new TestFormat();
@@ -56,7 +56,7 @@ namespace ImageSharp.Tests
exception = Assert.Throws(() =>
{
- Bootstrapper.Instance.AddImageFormat(format);
+ Bootstrapper.AddImageFormat(format);
});
Assert.Contains("decoder", exception.Message);
@@ -65,7 +65,7 @@ namespace ImageSharp.Tests
exception = Assert.Throws(() =>
{
- Bootstrapper.Instance.AddImageFormat(format);
+ Bootstrapper.AddImageFormat(format);
});
Assert.Contains("encoder", exception.Message);
@@ -74,7 +74,7 @@ namespace ImageSharp.Tests
exception = Assert.Throws(() =>
{
- Bootstrapper.Instance.AddImageFormat(format);
+ Bootstrapper.AddImageFormat(format);
});
Assert.Contains("mime type", exception.Message);
@@ -83,7 +83,7 @@ namespace ImageSharp.Tests
exception = Assert.Throws(() =>
{
- Bootstrapper.Instance.AddImageFormat(format);
+ Bootstrapper.AddImageFormat(format);
});
Assert.Contains("mime type", exception.Message);
@@ -92,7 +92,7 @@ namespace ImageSharp.Tests
exception = Assert.Throws(() =>
{
- Bootstrapper.Instance.AddImageFormat(format);
+ Bootstrapper.AddImageFormat(format);
});
Assert.Contains("extension", exception.Message);
@@ -101,7 +101,7 @@ namespace ImageSharp.Tests
exception = Assert.Throws(() =>
{
- Bootstrapper.Instance.AddImageFormat(format);
+ Bootstrapper.AddImageFormat(format);
});
Assert.Contains("extension", exception.Message);
@@ -110,7 +110,7 @@ namespace ImageSharp.Tests
exception = Assert.Throws(() =>
{
- Bootstrapper.Instance.AddImageFormat(format);
+ Bootstrapper.AddImageFormat(format);
});
Assert.Contains("supported extensions", exception.Message);
@@ -119,7 +119,7 @@ namespace ImageSharp.Tests
exception = Assert.Throws(() =>
{
- Bootstrapper.Instance.AddImageFormat(format);
+ Bootstrapper.AddImageFormat(format);
});
Assert.Contains("supported extensions", exception.Message);
}
@@ -131,28 +131,28 @@ namespace ImageSharp.Tests
var exception = Assert.Throws(() =>
{
- Bootstrapper.Instance.AddImageFormat(format);
+ Bootstrapper.AddImageFormat(format);
});
Assert.Contains("format with the same", exception.Message);
format.Extension = "test";
exception = Assert.Throws(() =>
{
- Bootstrapper.Instance.AddImageFormat(format);
+ Bootstrapper.AddImageFormat(format);
});
Assert.Contains("should contain", exception.Message);
format.SupportedExtensions = new string[] { "test", "jpg" };
exception = Assert.Throws(() =>
{
- Bootstrapper.Instance.AddImageFormat(format);
+ Bootstrapper.AddImageFormat(format);
});
Assert.Contains("supports the same", exception.Message);
format.SupportedExtensions = new string[] { "test", "" };
exception = Assert.Throws(() =>
{
- Bootstrapper.Instance.AddImageFormat(format);
+ Bootstrapper.AddImageFormat(format);
});
Assert.Contains("empty values", exception.Message);
}