Browse Source

Made all the Bootstrapper methods static and fixed thread safety issue.

Remove the Formats property from the Image<TColor, TPacked> class.
af/merge-core
Dirk Lemstra 9 years ago
parent
commit
47f70fe8cb
  1. 43
      src/ImageSharp/Bootstrapper.cs
  2. 6
      src/ImageSharp/Formats/Jpg/JpegDecoderCore.cs
  3. 19
      src/ImageSharp/Image/Image.cs
  4. 2
      src/ImageSharp/Image/ImageFrame.cs
  5. 2
      src/ImageSharp/ImageProcessor.cs
  6. 2
      src/ImageSharp/Quantizers/QuantizedImage.cs
  7. 2
      src/ImageSharp/Quantizers/Wu/WuQuantizer.cs
  8. 4
      tests/ImageSharp.Benchmarks/Image/CopyPixels.cs
  9. 26
      tests/ImageSharp.Tests/BootstrapperTests.cs

43
src/ImageSharp/Bootstrapper.cs

@ -19,16 +19,25 @@ namespace ImageSharp
public class Bootstrapper
{
/// <summary>
/// A new instance Initializes a new instance of the <see cref="Bootstrapper"/> class.
/// with lazy initialization.
/// A singleton of the <see cref="Bootstrapper"/> class.
/// </summary>
private static readonly Lazy<Bootstrapper> Lazy = new Lazy<Bootstrapper>(() => new Bootstrapper());
private static readonly Bootstrapper Instance = new Bootstrapper();
/// <summary>
/// The default list of supported <see cref="IImageFormat"/>
/// The list of supported <see cref="IImageFormat"/>.
/// </summary>
private readonly List<IImageFormat> imageFormats;
/// <summary>
/// The parallel options for processing tasks in parallel.
/// </summary>
private readonly ParallelOptions parallelOptions;
/// <summary>
/// An object that can be used to synchronize access to the <see cref="Bootstrapper"/>.
/// </summary>
private readonly object syncRoot = new object();
/// <summary>
/// Prevents a default instance of the <see cref="Bootstrapper"/> class from being created.
/// </summary>
@ -41,28 +50,24 @@ namespace ImageSharp
new PngFormat(),
new GifFormat()
};
this.parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount };
}
/// <summary>
/// Gets the current bootstrapper instance.
/// </summary>
public static Bootstrapper Instance => Lazy.Value;
/// <summary>
/// Gets the collection of supported <see cref="IImageFormat"/>
/// </summary>
public IReadOnlyCollection<IImageFormat> ImageFormats => new ReadOnlyCollection<IImageFormat>(this.imageFormats);
public static IReadOnlyCollection<IImageFormat> ImageFormats => new ReadOnlyCollection<IImageFormat>(Instance.imageFormats);
/// <summary>
/// Gets or sets the global parallel options for processing tasks in parallel.
/// Gets the global parallel options for processing tasks in parallel.
/// </summary>
public ParallelOptions ParallelOptions { get; set; } = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount };
public static ParallelOptions ParallelOptions => Instance.parallelOptions;
/// <summary>
/// Adds a new <see cref="IImageFormat"/> to the collection of supported image formats.
/// </summary>
/// <param name="format">The new format to add.</param>
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)

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

19
src/ImageSharp/Image/Image.cs

@ -43,7 +43,7 @@ namespace ImageSharp
/// </summary>
public Image()
{
this.CurrentImageFormat = Bootstrapper.Instance.ImageFormats.First(f => f.GetType() == typeof(PngFormat));
this.CurrentImageFormat = Bootstrapper.ImageFormats.First(f => f.GetType() == typeof(PngFormat));
}
/// <summary>
@ -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));
}
/// <summary>
@ -91,11 +91,6 @@ namespace ImageSharp
this.CopyProperties(other);
}
/// <summary>
/// Gets a list of supported image formats.
/// </summary>
public IReadOnlyCollection<IImageFormat> Formats { get; } = Bootstrapper.Instance.ImageFormats;
/// <summary>
/// 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
/// </exception>
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
/// </returns>
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);

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

2
src/ImageSharp/ImageProcessor.cs

@ -18,7 +18,7 @@ namespace ImageSharp.Processors
where TPacked : struct, IEquatable<TPacked>
{
/// <inheritdoc/>
public virtual ParallelOptions ParallelOptions { get; set; } = Bootstrapper.Instance.ParallelOptions;
public virtual ParallelOptions ParallelOptions { get; set; } = Bootstrapper.ParallelOptions;
/// <inheritdoc/>
public virtual bool Compand { get; set; } = false;

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

2
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<byte>.Shared.Rent(4);

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

26
tests/ImageSharp.Tests/BootstrapperTests.cs

@ -48,7 +48,7 @@ namespace ImageSharp.Tests
exception = Assert.Throws<ArgumentNullException>(() =>
{
Bootstrapper.Instance.AddImageFormat(null);
Bootstrapper.AddImageFormat(null);
});
var format = new TestFormat();
@ -56,7 +56,7 @@ namespace ImageSharp.Tests
exception = Assert.Throws<ArgumentNullException>(() =>
{
Bootstrapper.Instance.AddImageFormat(format);
Bootstrapper.AddImageFormat(format);
});
Assert.Contains("decoder", exception.Message);
@ -65,7 +65,7 @@ namespace ImageSharp.Tests
exception = Assert.Throws<ArgumentNullException>(() =>
{
Bootstrapper.Instance.AddImageFormat(format);
Bootstrapper.AddImageFormat(format);
});
Assert.Contains("encoder", exception.Message);
@ -74,7 +74,7 @@ namespace ImageSharp.Tests
exception = Assert.Throws<ArgumentNullException>(() =>
{
Bootstrapper.Instance.AddImageFormat(format);
Bootstrapper.AddImageFormat(format);
});
Assert.Contains("mime type", exception.Message);
@ -83,7 +83,7 @@ namespace ImageSharp.Tests
exception = Assert.Throws<ArgumentException>(() =>
{
Bootstrapper.Instance.AddImageFormat(format);
Bootstrapper.AddImageFormat(format);
});
Assert.Contains("mime type", exception.Message);
@ -92,7 +92,7 @@ namespace ImageSharp.Tests
exception = Assert.Throws<ArgumentNullException>(() =>
{
Bootstrapper.Instance.AddImageFormat(format);
Bootstrapper.AddImageFormat(format);
});
Assert.Contains("extension", exception.Message);
@ -101,7 +101,7 @@ namespace ImageSharp.Tests
exception = Assert.Throws<ArgumentException>(() =>
{
Bootstrapper.Instance.AddImageFormat(format);
Bootstrapper.AddImageFormat(format);
});
Assert.Contains("extension", exception.Message);
@ -110,7 +110,7 @@ namespace ImageSharp.Tests
exception = Assert.Throws<ArgumentNullException>(() =>
{
Bootstrapper.Instance.AddImageFormat(format);
Bootstrapper.AddImageFormat(format);
});
Assert.Contains("supported extensions", exception.Message);
@ -119,7 +119,7 @@ namespace ImageSharp.Tests
exception = Assert.Throws<ArgumentException>(() =>
{
Bootstrapper.Instance.AddImageFormat(format);
Bootstrapper.AddImageFormat(format);
});
Assert.Contains("supported extensions", exception.Message);
}
@ -131,28 +131,28 @@ namespace ImageSharp.Tests
var exception = Assert.Throws<ArgumentException>(() =>
{
Bootstrapper.Instance.AddImageFormat(format);
Bootstrapper.AddImageFormat(format);
});
Assert.Contains("format with the same", exception.Message);
format.Extension = "test";
exception = Assert.Throws<ArgumentException>(() =>
{
Bootstrapper.Instance.AddImageFormat(format);
Bootstrapper.AddImageFormat(format);
});
Assert.Contains("should contain", exception.Message);
format.SupportedExtensions = new string[] { "test", "jpg" };
exception = Assert.Throws<ArgumentException>(() =>
{
Bootstrapper.Instance.AddImageFormat(format);
Bootstrapper.AddImageFormat(format);
});
Assert.Contains("supports the same", exception.Message);
format.SupportedExtensions = new string[] { "test", "" };
exception = Assert.Throws<ArgumentException>(() =>
{
Bootstrapper.Instance.AddImageFormat(format);
Bootstrapper.AddImageFormat(format);
});
Assert.Contains("empty values", exception.Message);
}

Loading…
Cancel
Save