diff --git a/src/ImageSharp/Formats/ImageFormatManager.cs b/src/ImageSharp/Formats/ImageFormatManager.cs
index 63fd02d8d6..e62805d478 100644
--- a/src/ImageSharp/Formats/ImageFormatManager.cs
+++ b/src/ImageSharp/Formats/ImageFormatManager.cs
@@ -13,6 +13,12 @@ namespace SixLabors.ImageSharp.Formats
///
public class ImageFormatManager
{
+ ///
+ /// Used for locking against as there is no ConcurrentSet type.
+ ///
+ ///
+ private static readonly object HashLock = new object();
+
///
/// The list of supported keyed to mime types.
///
@@ -26,7 +32,7 @@ namespace SixLabors.ImageSharp.Formats
///
/// The list of supported s.
///
- private readonly ConcurrentBag imageFormats = new ConcurrentBag();
+ private readonly HashSet imageFormats = new HashSet();
///
/// The list of supported s.
@@ -74,7 +80,14 @@ namespace SixLabors.ImageSharp.Formats
Guard.NotNull(format, nameof(format));
Guard.NotNull(format.MimeTypes, nameof(format.MimeTypes));
Guard.NotNull(format.FileExtensions, nameof(format.FileExtensions));
- this.imageFormats.Add(format);
+
+ lock (HashLock)
+ {
+ if (!this.imageFormats.Contains(format))
+ {
+ this.imageFormats.Add(format);
+ }
+ }
}
///
@@ -86,9 +99,9 @@ namespace SixLabors.ImageSharp.Formats
{
Guard.NotNullOrWhiteSpace(extension, nameof(extension));
- if (extension[0] == '.')
- {
- extension = extension.Substring(1);
+ if (extension[0] == '.')
+ {
+ extension = extension.Substring(1);
}
return this.imageFormats.FirstOrDefault(x => x.FileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase));
diff --git a/tests/ImageSharp.Tests/ConfigurationTests.cs b/tests/ImageSharp.Tests/ConfigurationTests.cs
index 1a7183df81..4bec25f7a2 100644
--- a/tests/ImageSharp.Tests/ConfigurationTests.cs
+++ b/tests/ImageSharp.Tests/ConfigurationTests.cs
@@ -2,13 +2,9 @@
// 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 Moq;
+using SixLabors.ImageSharp.IO;
using Xunit;
// ReSharper disable InconsistentNaming
@@ -19,8 +15,8 @@ namespace SixLabors.ImageSharp.Tests
///
public class ConfigurationTests
{
- public Configuration ConfigurationEmpty { get; private set; }
- public Configuration DefaultConfiguration { get; private set; }
+ public Configuration ConfigurationEmpty { get; }
+ public Configuration DefaultConfiguration { get; }
public ConfigurationTests()
{
@@ -96,5 +92,26 @@ namespace SixLabors.ImageSharp.Tests
provider.Verify(x => x.Configure(config));
}
+
+ [Fact]
+ public void ConfigurationCannotAddDuplicates()
+ {
+ const int count = 4;
+ Configuration config = Configuration.Default;
+
+ Assert.Equal(count, config.ImageFormats.Count());
+
+ config.ImageFormatsManager.AddImageFormat(ImageFormats.Bmp);
+
+ Assert.Equal(count, config.ImageFormats.Count());
+ }
+
+ [Fact]
+ public void DefaultConfigurationHasCorrectFormatCount()
+ {
+ Configuration config = Configuration.Default;
+
+ Assert.Equal(4, config.ImageFormats.Count());
+ }
}
}
\ No newline at end of file
diff --git a/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs b/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs
index 740b30a8c3..496692d969 100644
--- a/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs
+++ b/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs
@@ -5,14 +5,14 @@ using System;
using System.Numerics;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
+using SixLabors.ImageSharp.Processing.Processors.Transforms;
+using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison;
using SixLabors.Primitives;
using Xunit;
namespace SixLabors.ImageSharp.Tests
{
- using SixLabors.ImageSharp.Processing;
- using SixLabors.ImageSharp.Processing.Processors.Transforms;
-
+ [GroupOutput("Drawing")]
public class DrawImageTest : FileTestBase
{
private const PixelTypes PixelTypes = Tests.PixelTypes.Rgba32;
@@ -41,11 +41,32 @@ namespace SixLabors.ImageSharp.Tests
using (var blend = Image.Load(TestFile.Create(TestImages.Bmp.Car).Bytes))
{
blend.Mutate(x => x.Resize(image.Width / 2, image.Height / 2));
- image.Mutate(x => x.DrawImage(blend, new Point(image.Width / 4, image.Height / 4), mode, .75f) );
+ image.Mutate(x => x.DrawImage(blend, new Point(image.Width / 4, image.Height / 4), mode, .75f));
image.DebugSave(provider, new { mode });
}
}
+ [Theory]
+ [WithFile(TestImages.Png.Rainbow, PixelTypes, PixelColorBlendingMode.Normal)]
+ [WithFile(TestImages.Png.Rainbow, PixelTypes, PixelColorBlendingMode.Multiply)]
+ [WithFile(TestImages.Png.Rainbow, PixelTypes, PixelColorBlendingMode.Add)]
+ [WithFile(TestImages.Png.Rainbow, PixelTypes, PixelColorBlendingMode.Subtract)]
+ [WithFile(TestImages.Png.Rainbow, PixelTypes, PixelColorBlendingMode.Screen)]
+ [WithFile(TestImages.Png.Rainbow, PixelTypes, PixelColorBlendingMode.Darken)]
+ [WithFile(TestImages.Png.Rainbow, PixelTypes, PixelColorBlendingMode.Lighten)]
+ [WithFile(TestImages.Png.Rainbow, PixelTypes, PixelColorBlendingMode.Overlay)]
+ [WithFile(TestImages.Png.Rainbow, PixelTypes, PixelColorBlendingMode.HardLight)]
+ public void ImageBlendingMatchesSvgSpecExamples(TestImageProvider provider, PixelColorBlendingMode mode)
+ where TPixel : struct, IPixel
+ {
+ using (Image background = provider.GetImage())
+ using (var source = Image.Load(TestFile.Create(TestImages.Png.Ducky).Bytes))
+ {
+ background.Mutate(x => x.DrawImage(source, mode, 1F));
+ VerifyImage(provider, mode, background);
+ }
+ }
+
[Theory]
[WithFileCollection(nameof(TestFiles), PixelTypes, PixelColorBlendingMode.Normal)]
public void ImageShouldDrawTransformedImage(TestImageProvider provider, PixelColorBlendingMode mode)
@@ -84,7 +105,7 @@ namespace SixLabors.ImageSharp.Tests
{
overlay.Mutate(x => x.Fill(Rgba32.Black));
- int xy = -25;
+ const int xy = -25;
Rgba32 backgroundPixel = background[0, 0];
Rgba32 overlayPixel = overlay[Math.Abs(xy) + 1, Math.Abs(xy) + 1];
@@ -106,7 +127,7 @@ namespace SixLabors.ImageSharp.Tests
{
overlay.Mutate(x => x.Fill(Rgba32.Black));
- int xy = 25;
+ const int xy = 25;
Rgba32 backgroundPixel = background[xy - 1, xy - 1];
Rgba32 overlayPixel = overlay[0, 0];
@@ -118,5 +139,25 @@ namespace SixLabors.ImageSharp.Tests
background.DebugSave(provider, testOutputDetails: "Positive");
}
}
+
+ private static void VerifyImage(
+ TestImageProvider provider,
+ PixelColorBlendingMode mode,
+ Image img)
+ where TPixel : struct, IPixel
+ {
+ img.DebugSave(
+ provider,
+ new { mode },
+ appendPixelTypeToFileName: false,
+ appendSourceFileOrDescription: false);
+
+ var comparer = ImageComparer.TolerantPercentage(0.01F, 3);
+ img.CompareFirstFrameToReferenceOutput(comparer,
+ provider,
+ new { mode },
+ appendPixelTypeToFileName: false,
+ appendSourceFileOrDescription: false);
+ }
}
}
\ No newline at end of file
diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs
index 5eb70117e3..1ee3f96757 100644
--- a/tests/ImageSharp.Tests/TestImages.cs
+++ b/tests/ImageSharp.Tests/TestImages.cs
@@ -68,6 +68,9 @@ namespace SixLabors.ImageSharp.Tests
public const string Ratio1x4 = "Png/ratio-1x4.png";
public const string Ratio4x1 = "Png/ratio-4x1.png";
+ public const string Ducky = "Png/ducky.png";
+ public const string Rainbow = "Png/rainbow.png";
+
public static class Bad
{
// Odd chunk lengths
diff --git a/tests/Images/External b/tests/Images/External
index 6a43d335f2..fcf311bf15 160000
--- a/tests/Images/External
+++ b/tests/Images/External
@@ -1 +1 @@
-Subproject commit 6a43d335f216d6325a6a9fd8d35942ade12b7c7b
+Subproject commit fcf311bf15bea061e552e4cc357cafe2d4f4bd70
diff --git a/tests/Images/Input/Png/ducky.png b/tests/Images/Input/Png/ducky.png
new file mode 100644
index 0000000000..8753a4a0e3
--- /dev/null
+++ b/tests/Images/Input/Png/ducky.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:0c2ea23adc981b8efba267c636b71190e74f798576467f26ed5cb4334a7ae421
+size 40960
diff --git a/tests/Images/Input/Png/rainbow.png b/tests/Images/Input/Png/rainbow.png
new file mode 100644
index 0000000000..78dfa1aad5
--- /dev/null
+++ b/tests/Images/Input/Png/rainbow.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:18993090b64a08939b4f8901e2b603bb8a49b053af7a0f327b4ae1205e64b987
+size 1447