Browse Source

Using Corecompat.System.Drawing as reference encoder/decoder for PNG. (Optimizing PNG-s with external tools from now.)

af/merge-core
Anton Firszov 9 years ago
parent
commit
1c18e70fbe
  1. 2
      src/ImageSharp/Configuration.cs
  2. 2
      src/ImageSharp/Image/ImageExtensions.cs
  3. 6
      tests/ImageSharp.Tests/Processing/Processors/Convolution/DetectEdgesTest.cs
  4. 13
      tests/ImageSharp.Tests/TestUtilities/ImageProviders/FileProvider.cs
  5. 42
      tests/ImageSharp.Tests/TestUtilities/ImagingTestCaseUtility.cs
  6. 4
      tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs
  7. 6
      tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceEncoder.cs
  8. 58
      tests/ImageSharp.Tests/TestUtilities/TestEnvironment.cs
  9. 4
      tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs
  10. 7
      tests/ImageSharp.Tests/TestUtilities/TestUtils.cs
  11. 4
      tests/ImageSharp.Tests/TestUtilities/Tests/ReferenceCodecTests.cs
  12. 24
      tests/ImageSharp.Tests/TestUtilities/Tests/TestEnvironmentTests.cs
  13. 2
      tests/ImageSharp.Tests/TestUtilities/Tests/TestUtilityExtensionsTests.cs
  14. 2
      tests/Images/External

2
src/ImageSharp/Configuration.cs

@ -140,7 +140,7 @@ namespace ImageSharp
/// </summary> /// </summary>
/// <param name="extension">The extension to discover</param> /// <param name="extension">The extension to discover</param>
/// <returns>The <see cref="IImageFormat"/> if found otherwise null</returns> /// <returns>The <see cref="IImageFormat"/> if found otherwise null</returns>
public IImageFormat FindFormatByFileExtensions(string extension) public IImageFormat FindFormatByFileExtension(string extension)
{ {
return this.imageFormats.FirstOrDefault(x => x.FileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase)); return this.imageFormats.FirstOrDefault(x => x.FileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase));
} }

2
src/ImageSharp/Image/ImageExtensions.cs

@ -52,7 +52,7 @@ namespace ImageSharp
Guard.NotNullOrEmpty(filePath, nameof(filePath)); Guard.NotNullOrEmpty(filePath, nameof(filePath));
string ext = Path.GetExtension(filePath).Trim('.'); string ext = Path.GetExtension(filePath).Trim('.');
IImageFormat format = source.Configuration.FindFormatByFileExtensions(ext); IImageFormat format = source.Configuration.FindFormatByFileExtension(ext);
if (format == null) if (format == null)
{ {
var stringBuilder = new StringBuilder(); var stringBuilder = new StringBuilder();

6
tests/ImageSharp.Tests/Processing/Processors/Convolution/DetectEdgesTest.cs

@ -40,7 +40,7 @@ namespace ImageSharp.Tests.Processing.Processors.Convolution
using (Image<TPixel> image = provider.GetImage()) using (Image<TPixel> image = provider.GetImage())
{ {
image.Mutate(x => x.DetectEdges(detector)); image.Mutate(x => x.DetectEdges(detector));
image.DebugSave(provider, detector.ToString(), grayscale: true); image.DebugSave(provider, detector.ToString());
} }
} }
@ -52,7 +52,7 @@ namespace ImageSharp.Tests.Processing.Processors.Convolution
using (Image<TPixel> image = provider.GetImage()) using (Image<TPixel> image = provider.GetImage())
{ {
image.Mutate(x => x.DetectEdges()); image.Mutate(x => x.DetectEdges());
image.DebugSave(provider, grayscale: true); image.DebugSave(provider);
} }
} }
@ -79,7 +79,7 @@ namespace ImageSharp.Tests.Processing.Processors.Convolution
var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2);
image.Mutate(x => x.DetectEdges(bounds)); image.Mutate(x => x.DetectEdges(bounds));
image.DebugSave(provider, grayscale: true); image.DebugSave(provider);
// TODO: We don't need this any longer after switching to ReferenceImages // TODO: We don't need this any longer after switching to ReferenceImages
ImageComparer.Tolerant().EnsureProcessorChangesAreConstrained(source, image, bounds); ImageComparer.Tolerant().EnsureProcessorChangesAreConstrained(source, image, bounds);

13
tests/ImageSharp.Tests/TestUtilities/ImageProviders/FileProvider.cs

@ -45,17 +45,8 @@ namespace ImageSharp.Tests
public override Image<TPixel> GetImage() public override Image<TPixel> GetImage()
{ {
Key key = new Key(this.PixelType, this.FilePath); IImageDecoder decoder = TestEnvironment.GetReferenceDecoder(this.FilePath);
return this.GetImage(decoder);
Image<TPixel> cachedImage = cache.GetOrAdd(
key,
fn =>
{
TestFile testFile = TestFile.Create(this.FilePath);
return Image.Load<TPixel>(testFile.Bytes);
});
return cachedImage.Clone();
} }
public override Image<TPixel> GetImage(IImageDecoder decoder) public override Image<TPixel> GetImage(IImageDecoder decoder)

42
tests/ImageSharp.Tests/TestUtilities/ImagingTestCaseUtility.cs

@ -138,13 +138,11 @@ namespace ImageSharp.Tests
string extension = null, string extension = null,
IImageEncoder encoder = null, IImageEncoder encoder = null,
object testOutputDetails = null, object testOutputDetails = null,
bool grayscale = false,
bool appendPixelTypeToFileName = true) bool appendPixelTypeToFileName = true)
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
string path = this.GetTestOutputFileName(extension, testOutputDetails, appendPixelTypeToFileName); string path = this.GetTestOutputFileName(extension, testOutputDetails, appendPixelTypeToFileName);
string extension1 = Path.GetExtension(path); encoder = encoder ?? TestEnvironment.GetReferenceEncoder(path);
encoder = encoder ?? GetImageFormatByExtension(extension1, grayscale);
using (FileStream stream = File.OpenWrite(path)) using (FileStream stream = File.OpenWrite(path))
{ {
@ -173,26 +171,26 @@ namespace ImageSharp.Tests
this.Init(method.DeclaringType.Name, method.Name); this.Init(method.DeclaringType.Name, method.Name);
} }
private static IImageEncoder GetImageFormatByExtension(string extension, bool grayscale) //private static IImageEncoder GetEncoderByExtension(string extension, bool grayscale)
{ //{
extension = extension?.TrimStart('.'); // extension = extension?.TrimStart('.');
var format = Configuration.Default.FindFormatByFileExtensions(extension); // var format = Configuration.Default.FindFormatByFileExtension(extension);
IImageEncoder encoder = Configuration.Default.FindEncoder(format); // IImageEncoder encoder = Configuration.Default.FindEncoder(format);
PngEncoder pngEncoder = encoder as PngEncoder; // PngEncoder pngEncoder = encoder as PngEncoder;
if (pngEncoder != null) // if (pngEncoder != null)
{ // {
pngEncoder = new PngEncoder(); // pngEncoder = new PngEncoder();
encoder = pngEncoder; // encoder = pngEncoder;
pngEncoder.CompressionLevel = 9; // pngEncoder.CompressionLevel = 9;
if (grayscale) // if (grayscale)
{ // {
pngEncoder.PngColorType = PngColorType.Grayscale; // pngEncoder.PngColorType = PngColorType.Grayscale;
} // }
} // }
return encoder; // return encoder;
} //}
private string GetTestOutputDir() private string GetTestOutputDir()
{ {

4
tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/ReferenceDecoder.cs → tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs

@ -8,9 +8,9 @@ namespace ImageSharp.Tests.TestUtilities.ReferenceCodecs
using ImageSharp.Formats; using ImageSharp.Formats;
using ImageSharp.PixelFormats; using ImageSharp.PixelFormats;
public class ReferenceDecoder : IImageDecoder public class SystemDrawingReferenceDecoder : IImageDecoder
{ {
public static ReferenceDecoder Instance { get; } = new ReferenceDecoder(); public static SystemDrawingReferenceDecoder Instance { get; } = new SystemDrawingReferenceDecoder();
public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream) public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream)
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>

6
tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/ReferenceEncoder.cs → tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceEncoder.cs

@ -9,16 +9,16 @@ namespace ImageSharp.Tests.TestUtilities.ReferenceCodecs
using ImageSharp.Formats; using ImageSharp.Formats;
using ImageSharp.PixelFormats; using ImageSharp.PixelFormats;
public class ReferenceEncoder : IImageEncoder public class SystemDrawingReferenceEncoder : IImageEncoder
{ {
private readonly System.Drawing.Imaging.ImageFormat imageFormat; private readonly System.Drawing.Imaging.ImageFormat imageFormat;
public ReferenceEncoder(ImageFormat imageFormat) public SystemDrawingReferenceEncoder(ImageFormat imageFormat)
{ {
this.imageFormat = imageFormat; this.imageFormat = imageFormat;
} }
public static ReferenceEncoder Png { get; } = new ReferenceEncoder(System.Drawing.Imaging.ImageFormat.Png); public static SystemDrawingReferenceEncoder Png { get; } = new SystemDrawingReferenceEncoder(System.Drawing.Imaging.ImageFormat.Png);
public void Encode<TPixel>(Image<TPixel> image, Stream stream) public void Encode<TPixel>(Image<TPixel> image, Stream stream)
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>

58
tests/ImageSharp.Tests/TestUtilities/TestEnvironment.cs

@ -1,12 +1,13 @@
namespace ImageSharp.Tests namespace ImageSharp.Tests
{ {
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Security;
using ImageSharp.Formats;
using ImageSharp.Tests.TestUtilities.ReferenceCodecs;
public static class TestEnvironment public static class TestEnvironment
{ {
private const string ImageSharpSolutionFileName = "ImageSharp.sln"; private const string ImageSharpSolutionFileName = "ImageSharp.sln";
@ -26,6 +27,8 @@ namespace ImageSharp.Tests
return bool.TryParse(Environment.GetEnvironmentVariable("CI"), out isCi) && isCi; return bool.TryParse(Environment.GetEnvironmentVariable("CI"), out isCi) && isCi;
}); });
private static Lazy<Configuration> configuration = new Lazy<Configuration>(CreateDefaultConfiguration);
// ReSharper disable once InconsistentNaming // ReSharper disable once InconsistentNaming
/// <summary> /// <summary>
/// Gets a value indicating whether test execution runs on CI. /// Gets a value indicating whether test execution runs on CI.
@ -34,6 +37,24 @@ namespace ImageSharp.Tests
internal static string SolutionDirectoryFullPath => solutionDirectoryFullPath.Value; internal static string SolutionDirectoryFullPath => solutionDirectoryFullPath.Value;
internal static Configuration Configuration => configuration.Value;
private static Configuration CreateDefaultConfiguration()
{
var configuration = new Configuration(
new PngConfigurationModule(),
new JpegConfigurationModule(),
new GifConfigurationModule(),
new BmpConfigurationModule()
);
configuration.SetDecoder(ImageFormats.Png, SystemDrawingReferenceDecoder.Instance);
configuration.SetEncoder(ImageFormats.Png, SystemDrawingReferenceEncoder.Png);
configuration.AddImageFormatDetector(new PngImageFormatDetector());
return configuration;
}
private static string GetSolutionDirectoryFullPathImpl() private static string GetSolutionDirectoryFullPathImpl()
{ {
string assemblyLocation = typeof(TestFile).GetTypeInfo().Assembly.Location; string assemblyLocation = typeof(TestFile).GetTypeInfo().Assembly.Location;
@ -62,23 +83,48 @@ namespace ImageSharp.Tests
return directory.FullName; return directory.FullName;
} }
/// <summary> /// <summary>
/// Gets the correct full path to the Input Images directory. /// Gets the correct full path to the Input Images directory.
/// </summary> /// </summary>
internal static string InputImagesDirectoryFullPath => Path.Combine(SolutionDirectoryFullPath, InputImagesRelativePath); internal static string InputImagesDirectoryFullPath =>
Path.Combine(SolutionDirectoryFullPath, InputImagesRelativePath);
/// <summary> /// <summary>
/// Gets the correct full path to the Actual Output directory. (To be written to by the test cases.) /// Gets the correct full path to the Actual Output directory. (To be written to by the test cases.)
/// </summary> /// </summary>
internal static string ActualOutputDirectoryFullPath => Path.Combine(SolutionDirectoryFullPath, ActualOutputDirectoryRelativePath); internal static string ActualOutputDirectoryFullPath => Path.Combine(
SolutionDirectoryFullPath,
ActualOutputDirectoryRelativePath);
/// <summary> /// <summary>
/// Gets the correct full path to the Expected Output directory. (To compare the test results to.) /// Gets the correct full path to the Expected Output directory. (To compare the test results to.)
/// </summary> /// </summary>
internal static string ReferenceOutputDirectoryFullPath => Path.Combine(SolutionDirectoryFullPath, ReferenceOutputDirectoryRelativePath); internal static string ReferenceOutputDirectoryFullPath => Path.Combine(
SolutionDirectoryFullPath,
ReferenceOutputDirectoryRelativePath);
internal static string GetReferenceOutputFileName(string actualOutputFileName) => internal static string GetReferenceOutputFileName(string actualOutputFileName) =>
actualOutputFileName.Replace("ActualOutput", @"External\ReferenceOutput"); actualOutputFileName.Replace("ActualOutput", @"External\ReferenceOutput");
internal static IImageDecoder GetReferenceDecoder(string filePath)
{
IImageFormat format = GetImageFormat(filePath);
return Configuration.FindDecoder(format);
}
internal static IImageEncoder GetReferenceEncoder(string filePath)
{
IImageFormat format = GetImageFormat(filePath);
return Configuration.FindEncoder(format);
}
private static IImageFormat GetImageFormat(string filePath)
{
string extension = Path.GetExtension(filePath).ToLower();
if (extension[0] == '.') extension = extension.Substring(1);
IImageFormat format = Configuration.FindFormatByFileExtension(extension);
return format;
}
} }
} }

4
tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs

@ -29,7 +29,6 @@ namespace ImageSharp.Tests
ITestImageProvider provider, ITestImageProvider provider,
object testOutputDetails = null, object testOutputDetails = null,
string extension = "png", string extension = "png",
bool grayscale = false,
bool appendPixelTypeToFileName = true) bool appendPixelTypeToFileName = true)
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
@ -43,7 +42,6 @@ namespace ImageSharp.Tests
image, image,
extension, extension,
testOutputDetails: testOutputDetails, testOutputDetails: testOutputDetails,
grayscale: grayscale,
appendPixelTypeToFileName: appendPixelTypeToFileName); appendPixelTypeToFileName: appendPixelTypeToFileName);
return image; return image;
} }
@ -139,7 +137,7 @@ namespace ImageSharp.Tests
var testFile = TestFile.Create(path); var testFile = TestFile.Create(path);
using (var original = Image.Load<TPixel>(testFile.Bytes, ReferenceDecoder.Instance)) using (var original = Image.Load<TPixel>(testFile.Bytes, SystemDrawingReferenceDecoder.Instance))
{ {
//original.DebugSave(provider, "__SYSTEMDRAWING__"); //original.DebugSave(provider, "__SYSTEMDRAWING__");
comparer.VerifySimilarity(original, image); comparer.VerifySimilarity(original, image);

7
tests/ImageSharp.Tests/TestUtilities/TestUtilityExtensions.cs → tests/ImageSharp.Tests/TestUtilities/TestUtils.cs

@ -11,12 +11,13 @@ namespace ImageSharp.Tests
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using ImageSharp.Formats;
using ImageSharp.PixelFormats; using ImageSharp.PixelFormats;
/// <summary> /// <summary>
/// Extension methods for TestUtilities /// Various utility and extension methods.
/// </summary> /// </summary>
public static class TestUtilityExtensions public static class TestUtils
{ {
private static readonly Dictionary<Type, PixelTypes> ClrTypes2PixelTypes = new Dictionary<Type, PixelTypes>(); private static readonly Dictionary<Type, PixelTypes> ClrTypes2PixelTypes = new Dictionary<Type, PixelTypes>();
@ -28,7 +29,7 @@ namespace ImageSharp.Tests
.Except(new[] { PixelTypes.Undefined, PixelTypes.All }) .Except(new[] { PixelTypes.Undefined, PixelTypes.All })
.ToArray(); .ToArray();
static TestUtilityExtensions() static TestUtils()
{ {
// Add Rgba32 Our default. // Add Rgba32 Our default.
Type defaultPixelFormatType = typeof(Rgba32); Type defaultPixelFormatType = typeof(Rgba32);

4
tests/ImageSharp.Tests/TestUtilities/Tests/ReferenceCodecTests.cs

@ -52,7 +52,7 @@ namespace ImageSharp.Tests
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
string path = TestFile.GetInputFileFullPath(TestImages.Png.Splash); string path = TestFile.GetInputFileFullPath(TestImages.Png.Splash);
using (Image<TPixel> image = Image.Load<TPixel>(path, ReferenceDecoder.Instance)) using (Image<TPixel> image = Image.Load<TPixel>(path, SystemDrawingReferenceDecoder.Instance))
{ {
image.DebugSave(dummyProvider); image.DebugSave(dummyProvider);
} }
@ -65,7 +65,7 @@ namespace ImageSharp.Tests
{ {
using (Image<TPixel> image = provider.GetImage()) using (Image<TPixel> image = provider.GetImage())
{ {
provider.Utility.SaveTestOutputFile(image, "png", ReferenceEncoder.Png); provider.Utility.SaveTestOutputFile(image, "png", SystemDrawingReferenceEncoder.Png);
} }
} }
} }

24
tests/ImageSharp.Tests/TestUtilities/Tests/TestEnvironmentTests.cs

@ -6,8 +6,12 @@
// ReSharper disable InconsistentNaming // ReSharper disable InconsistentNaming
namespace ImageSharp.Tests namespace ImageSharp.Tests
{ {
using System;
using System.IO; using System.IO;
using ImageSharp.Formats;
using ImageSharp.Tests.TestUtilities.ReferenceCodecs;
using Xunit; using Xunit;
using Xunit.Abstractions; using Xunit.Abstractions;
@ -59,5 +63,25 @@ namespace ImageSharp.Tests
this.Output.WriteLine(expected); this.Output.WriteLine(expected);
Assert.Contains(TestEnvironment.ReferenceOutputDirectoryFullPath, expected); Assert.Contains(TestEnvironment.ReferenceOutputDirectoryFullPath, expected);
} }
[Theory]
[InlineData("lol/foo.png", typeof(SystemDrawingReferenceEncoder))]
[InlineData("lol/Baz.JPG", typeof(JpegEncoder))]
[InlineData("lol/Baz.gif", typeof(GifEncoder))]
public void GetReferenceEncoder_ReturnsCorrectEncoders(string fileName, Type expectedEncoderType)
{
IImageEncoder encoder = TestEnvironment.GetReferenceEncoder(fileName);
Assert.IsType(expectedEncoderType, encoder);
}
[Theory]
[InlineData("lol/foo.png", typeof(SystemDrawingReferenceDecoder))]
[InlineData("lol/Baz.JPG", typeof(JpegDecoder))]
[InlineData("lol/Baz.gif", typeof(GifDecoder))]
public void GetReferenceDecoder_ReturnsCorrectEncoders(string fileName, Type expectedDecoderType)
{
IImageDecoder decoder = TestEnvironment.GetReferenceDecoder(fileName);
Assert.IsType(expectedDecoderType, decoder);
}
} }
} }

2
tests/ImageSharp.Tests/TestUtilities/Tests/TestUtilityExtensionsTests.cs

@ -147,7 +147,7 @@ namespace ImageSharp.Tests
{ {
KeyValuePair<PixelTypes, Type>[] expanded = PixelTypes.All.ExpandAllTypes().ToArray(); KeyValuePair<PixelTypes, Type>[] expanded = PixelTypes.All.ExpandAllTypes().ToArray();
Assert.True(expanded.Length >= TestUtilityExtensions.GetAllPixelTypes().Length - 2); Assert.True(expanded.Length >= TestUtils.GetAllPixelTypes().Length - 2);
AssertContainsPixelType<Rgba32>(PixelTypes.Rgba32, expanded); AssertContainsPixelType<Rgba32>(PixelTypes.Rgba32, expanded);
AssertContainsPixelType<Rgba32>(PixelTypes.Rgba32, expanded); AssertContainsPixelType<Rgba32>(PixelTypes.Rgba32, expanded);
} }

2
tests/Images/External

@ -1 +1 @@
Subproject commit 6996009ff537d1c9cbc2b93d692cd89bf8f2a5c7 Subproject commit 4929cbe0d743fe3c67a9b4d0c71fb3eed8b5537d
Loading…
Cancel
Save