Browse Source

cleanup

js/color-alpha-handling
James Jackson-South 5 years ago
parent
commit
71801bfbb6
  1. 19
      tests/ImageSharp.Benchmarks/BenchmarkBase.cs
  2. 29
      tests/ImageSharp.Benchmarks/Codecs/DecodeBmp.cs
  3. 48
      tests/ImageSharp.Benchmarks/Codecs/DecodeFilteredPng.cs
  4. 29
      tests/ImageSharp.Benchmarks/Codecs/DecodeGif.cs
  5. 29
      tests/ImageSharp.Benchmarks/Codecs/DecodePng.cs
  6. 34
      tests/ImageSharp.Benchmarks/Codecs/DecodeTga.cs
  7. 23
      tests/ImageSharp.Benchmarks/Codecs/EncodeBmp.cs
  8. 10
      tests/ImageSharp.Benchmarks/Codecs/EncodeBmpMultiple.cs
  9. 19
      tests/ImageSharp.Benchmarks/Codecs/EncodeGif.cs
  10. 10
      tests/ImageSharp.Benchmarks/Codecs/EncodeGifMultiple.cs
  11. 59
      tests/ImageSharp.Benchmarks/Codecs/EncodeIndexedPng.cs
  12. 19
      tests/ImageSharp.Benchmarks/Codecs/EncodePng.cs
  13. 34
      tests/ImageSharp.Benchmarks/Codecs/EncodeTga.cs
  14. 32
      tests/ImageSharp.Benchmarks/Codecs/GetSetPixel.cs
  15. 16
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/CmykColorConversion.cs
  16. 20
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversionBenchmark.cs
  17. 7
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpegParseStreamOnly.cs
  18. 16
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpeg_Aggregate.cs
  19. 20
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpeg_ImageSpecific.cs
  20. 32
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/EncodeJpeg.cs
  21. 10
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/EncodeJpegMultiple.cs
  22. 10
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/GrayscaleColorConversion.cs
  23. 13
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/IdentifyJpeg.cs
  24. 64
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/LoadResizeSave_Aggregate.cs
  25. 32
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/LoadResizeSave_ImageSpecific.cs
  26. 14
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/RgbColorConversion.cs
  27. 19
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/YCbCrColorConversion.cs
  28. 14
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/YccKColorConverter.cs
  29. 112
      tests/ImageSharp.Benchmarks/Codecs/MultiImageBenchmarkBase.cs
  30. 2
      tests/ImageSharp.Benchmarks/Color/Bulk/FromVector4_Rgb24.cs
  31. 2
      tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4_Bgra32.cs
  32. 2
      tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4_Rgb24.cs
  33. 8
      tests/ImageSharp.Benchmarks/Config.cs
  34. 2
      tests/ImageSharp.Benchmarks/General/Adler32Benchmark.cs
  35. 2
      tests/ImageSharp.Benchmarks/General/CopyBuffers.cs
  36. 2
      tests/ImageSharp.Benchmarks/General/Crc32Benchmark.cs
  37. 28
      tests/ImageSharp.Benchmarks/General/GetSetPixel.cs
  38. 2
      tests/ImageSharp.Benchmarks/General/IO/BufferedStreams.cs
  39. 2
      tests/ImageSharp.Benchmarks/General/Vectorization/UInt32ToSingle.cs
  40. 2
      tests/ImageSharp.Benchmarks/General/Vectorization/WidenBytesToUInt32.cs
  41. 2
      tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj
  42. 86
      tests/ImageSharp.Benchmarks/PixelBlenders/PorterDuffBulkVsPixel.cs
  43. 8
      tests/ImageSharp.Benchmarks/Processing/BokehBlur.cs
  44. 40
      tests/ImageSharp.Benchmarks/Processing/Crop.cs
  45. 20
      tests/ImageSharp.Benchmarks/Processing/DetectEdges.cs
  46. 20
      tests/ImageSharp.Benchmarks/Processing/Diffuse.cs
  47. 6
      tests/ImageSharp.Benchmarks/Processing/GaussianBlur.cs
  48. 31
      tests/ImageSharp.Benchmarks/Processing/HistogramEqualization.cs
  49. 36
      tests/ImageSharp.Benchmarks/Processing/Resize.cs
  50. 12
      tests/ImageSharp.Benchmarks/Processing/Rotate.cs
  51. 12
      tests/ImageSharp.Benchmarks/Processing/Skew.cs
  52. 45
      tests/ImageSharp.Benchmarks/Samplers/Crop.cs

19
tests/ImageSharp.Benchmarks/BenchmarkBase.cs

@ -1,19 +0,0 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
namespace SixLabors.ImageSharp.Benchmarks
{
/// <summary>
/// The image benchmark base class.
/// </summary>
public abstract class BenchmarkBase
{
/// <summary>
/// Initializes a new instance of the <see cref="BenchmarkBase"/> class.
/// </summary>
protected BenchmarkBase()
{
// Add Image Formats
}
}
}

29
tests/ImageSharp.Benchmarks/Codecs/DecodeBmp.cs

@ -10,12 +10,13 @@ using SDSize = System.Drawing.Size;
namespace SixLabors.ImageSharp.Benchmarks.Codecs
{
[Config(typeof(Config.ShortClr))]
public class DecodeBmp : BenchmarkBase
[Config(typeof(Config.ShortMultiFramework))]
public class DecodeBmp
{
private byte[] bmpBytes;
private string TestImageFullPath => Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, this.TestImage);
private string TestImageFullPath
=> Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, this.TestImage);
[GlobalSetup]
public void ReadImages()
@ -32,25 +33,17 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
[Benchmark(Baseline = true, Description = "System.Drawing Bmp")]
public SDSize BmpSystemDrawing()
{
using (var memoryStream = new MemoryStream(this.bmpBytes))
{
using (var image = SDImage.FromStream(memoryStream))
{
return image.Size;
}
}
using var memoryStream = new MemoryStream(this.bmpBytes);
using var image = SDImage.FromStream(memoryStream);
return image.Size;
}
[Benchmark(Description = "ImageSharp Bmp")]
public Size BmpCore()
public Size BmpImageSharp()
{
using (var memoryStream = new MemoryStream(this.bmpBytes))
{
using (var image = Image.Load<Rgba32>(memoryStream))
{
return new Size(image.Width, image.Height);
}
}
using var memoryStream = new MemoryStream(this.bmpBytes);
using var image = Image.Load<Rgba32>(memoryStream);
return new Size(image.Width, image.Height);
}
}
}

48
tests/ImageSharp.Benchmarks/Codecs/DecodeFilteredPng.cs

@ -6,12 +6,11 @@ using System.Runtime.CompilerServices;
using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Tests;
using CoreSize = SixLabors.ImageSharp.Size;
namespace SixLabors.ImageSharp.Benchmarks.Codecs
{
[Config(typeof(Config.ShortClr))]
public class DecodeFilteredPng : BenchmarkBase
[Config(typeof(Config.ShortMultiFramework))]
public class DecodeFilteredPng
{
private byte[] filter0;
private byte[] filter1;
@ -30,44 +29,33 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
}
[Benchmark(Baseline = true, Description = "None-filtered PNG file")]
public CoreSize PngFilter0()
{
return LoadPng(this.filter0);
}
public Size PngFilter0()
=> LoadPng(this.filter0);
[Benchmark(Description = "Sub-filtered PNG file")]
public CoreSize PngFilter1()
{
return LoadPng(this.filter1);
}
public Size PngFilter1()
=> LoadPng(this.filter1);
[Benchmark(Description = "Up-filtered PNG file")]
public CoreSize PngFilter2()
{
return LoadPng(this.filter2);
}
public Size PngFilter2()
=> LoadPng(this.filter2);
[Benchmark(Description = "Average-filtered PNG file")]
public CoreSize PngFilter3()
{
return LoadPng(this.filter3);
}
public Size PngFilter3()
=> LoadPng(this.filter3);
[Benchmark(Description = "Paeth-filtered PNG file")]
public CoreSize PngFilter4()
{
return LoadPng(this.filter4);
}
public Size PngFilter4()
=> LoadPng(this.filter4);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static CoreSize LoadPng(byte[] bytes)
private static Size LoadPng(byte[] bytes)
{
using (var image = Image.Load<Rgba32>(bytes))
{
return image.Size();
}
using var image = Image.Load<Rgba32>(bytes);
return image.Size();
}
private static string TestImageFullPath(string path) => Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, path);
private static string TestImageFullPath(string path)
=> Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, path);
}
}
}

29
tests/ImageSharp.Benchmarks/Codecs/DecodeGif.cs

@ -10,12 +10,13 @@ using SDSize = System.Drawing.Size;
namespace SixLabors.ImageSharp.Benchmarks.Codecs
{
[Config(typeof(Config.ShortClr))]
public class DecodeGif : BenchmarkBase
[Config(typeof(Config.ShortMultiFramework))]
public class DecodeGif
{
private byte[] gifBytes;
private string TestImageFullPath => Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, this.TestImage);
private string TestImageFullPath
=> Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, this.TestImage);
[GlobalSetup]
public void ReadImages()
@ -32,25 +33,17 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
[Benchmark(Baseline = true, Description = "System.Drawing Gif")]
public SDSize GifSystemDrawing()
{
using (var memoryStream = new MemoryStream(this.gifBytes))
{
using (var image = SDImage.FromStream(memoryStream))
{
return image.Size;
}
}
using var memoryStream = new MemoryStream(this.gifBytes);
using var image = SDImage.FromStream(memoryStream);
return image.Size;
}
[Benchmark(Description = "ImageSharp Gif")]
public Size GifCore()
public Size GifImageSharp()
{
using (var memoryStream = new MemoryStream(this.gifBytes))
{
using (var image = Image.Load<Rgba32>(memoryStream))
{
return new Size(image.Width, image.Height);
}
}
using var memoryStream = new MemoryStream(this.gifBytes);
using var image = Image.Load<Rgba32>(memoryStream);
return new Size(image.Width, image.Height);
}
}
}

29
tests/ImageSharp.Benchmarks/Codecs/DecodePng.cs

@ -10,12 +10,13 @@ using SDSize = System.Drawing.Size;
namespace SixLabors.ImageSharp.Benchmarks.Codecs
{
[Config(typeof(Config.ShortClr))]
public class DecodePng : BenchmarkBase
[Config(typeof(Config.ShortMultiFramework))]
public class DecodePng
{
private byte[] pngBytes;
private string TestImageFullPath => Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, this.TestImage);
private string TestImageFullPath
=> Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, this.TestImage);
[Params(TestImages.Png.Splash)]
public string TestImage { get; set; }
@ -32,25 +33,17 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
[Benchmark(Baseline = true, Description = "System.Drawing Png")]
public SDSize PngSystemDrawing()
{
using (var memoryStream = new MemoryStream(this.pngBytes))
{
using (var image = SDImage.FromStream(memoryStream))
{
return image.Size;
}
}
using var memoryStream = new MemoryStream(this.pngBytes);
using var image = SDImage.FromStream(memoryStream);
return image.Size;
}
[Benchmark(Description = "ImageSharp Png")]
public Size PngCore()
public Size PngImageSharp()
{
using (var memoryStream = new MemoryStream(this.pngBytes))
{
using (var image = Image.Load<Rgba32>(memoryStream))
{
return image.Size();
}
}
using var memoryStream = new MemoryStream(this.pngBytes);
using var image = Image.Load<Rgba32>(memoryStream);
return image.Size();
}
}
}

34
tests/ImageSharp.Benchmarks/Codecs/DecodeTga.cs

@ -5,7 +5,6 @@ using System.Buffers;
using System.IO;
using System.Threading;
using BenchmarkDotNet.Attributes;
using ImageMagick;
using Pfim;
using SixLabors.ImageSharp.Formats.Tga;
@ -14,8 +13,8 @@ using SixLabors.ImageSharp.Tests;
namespace SixLabors.ImageSharp.Benchmarks.Codecs
{
[Config(typeof(Config.ShortClr))]
public class DecodeTga : BenchmarkBase
[Config(typeof(Config.ShortMultiFramework))]
public class DecodeTga
{
private string TestImageFullPath => Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, this.TestImage);
@ -28,36 +27,28 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
[GlobalSetup]
public void SetupData()
{
this.data = File.ReadAllBytes(this.TestImageFullPath);
}
=> this.data = File.ReadAllBytes(this.TestImageFullPath);
[Benchmark(Baseline = true, Description = "ImageMagick Tga")]
public int TgaImageMagick()
{
var settings = new MagickReadSettings { Format = MagickFormat.Tga };
using (var image = new MagickImage(new MemoryStream(this.data), settings))
{
return image.Width;
}
using var image = new MagickImage(new MemoryStream(this.data), settings);
return image.Width;
}
[Benchmark(Description = "ImageSharp Tga")]
public int TgaCore()
public int TgaImageSharp()
{
using (var image = Image.Load<Bgr24>(this.data, new TgaDecoder()))
{
return image.Width;
}
using var image = Image.Load<Bgr24>(this.data, new TgaDecoder());
return image.Width;
}
[Benchmark(Description = "Pfim Tga")]
public int TgaPfim()
{
using (var image = Targa.Create(this.data, this.pfimConfig))
{
return image.Width;
}
using var image = Targa.Create(this.data, this.pfimConfig);
return image.Width;
}
private class PfimAllocator : IImageAllocator
@ -65,10 +56,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
private int rented;
private readonly ArrayPool<byte> shared = ArrayPool<byte>.Shared;
public byte[] Rent(int size)
{
return this.shared.Rent(size);
}
public byte[] Rent(int size) => this.shared.Rent(size);
public void Return(byte[] data)
{

23
tests/ImageSharp.Benchmarks/Codecs/EncodeBmp.cs

@ -1,4 +1,4 @@
// Copyright (c) Six Labors.
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System.Drawing.Imaging;
@ -10,8 +10,8 @@ using SDImage = System.Drawing.Image;
namespace SixLabors.ImageSharp.Benchmarks.Codecs
{
[Config(typeof(Config.ShortClr))]
public class EncodeBmp : BenchmarkBase
[Config(typeof(Config.ShortMultiFramework))]
public class EncodeBmp
{
private Stream bmpStream;
private SDImage bmpDrawing;
@ -33,6 +33,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
public void Cleanup()
{
this.bmpStream.Dispose();
this.bmpStream = null;
this.bmpCore.Dispose();
this.bmpDrawing.Dispose();
}
@ -40,19 +41,15 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
[Benchmark(Baseline = true, Description = "System.Drawing Bmp")]
public void BmpSystemDrawing()
{
using (var memoryStream = new MemoryStream())
{
this.bmpDrawing.Save(memoryStream, ImageFormat.Bmp);
}
using var memoryStream = new MemoryStream();
this.bmpDrawing.Save(memoryStream, ImageFormat.Bmp);
}
[Benchmark(Description = "ImageSharp Bmp")]
public void BmpCore()
public void BmpImageSharp()
{
using (var memoryStream = new MemoryStream())
{
this.bmpCore.SaveAsBmp(memoryStream);
}
using var memoryStream = new MemoryStream();
this.bmpCore.SaveAsBmp(memoryStream);
}
}
}
}

10
tests/ImageSharp.Benchmarks/Codecs/EncodeBmpMultiple.cs

@ -8,29 +8,25 @@ using SixLabors.ImageSharp.Formats.Bmp;
namespace SixLabors.ImageSharp.Benchmarks.Codecs
{
[Config(typeof(Config.ShortClr))]
[Config(typeof(Config.ShortMultiFramework))]
public class EncodeBmpMultiple : MultiImageBenchmarkBase.WithImagesPreloaded
{
protected override IEnumerable<string> InputImageSubfoldersOrFiles => new[] { "Bmp/", "Jpg/baseline" };
[Benchmark(Description = "EncodeBmpMultiple - ImageSharp")]
public void EncodeBmpImageSharp()
{
this.ForEachImageSharpImage((img, ms) =>
=> this.ForEachImageSharpImage((img, ms) =>
{
img.Save(ms, new BmpEncoder());
return null;
});
}
[Benchmark(Baseline = true, Description = "EncodeBmpMultiple - System.Drawing")]
public void EncodeBmpSystemDrawing()
{
this.ForEachSystemDrawingImage((img, ms) =>
=> this.ForEachSystemDrawingImage((img, ms) =>
{
img.Save(ms, ImageFormat.Bmp);
return null;
});
}
}
}

19
tests/ImageSharp.Benchmarks/Codecs/EncodeGif.cs

@ -13,8 +13,8 @@ using SDImage = System.Drawing.Image;
namespace SixLabors.ImageSharp.Benchmarks.Codecs
{
[Config(typeof(Config.ShortClr))]
public class EncodeGif : BenchmarkBase
[Config(typeof(Config.ShortMultiFramework))]
public class EncodeGif
{
// System.Drawing needs this.
private Stream bmpStream;
@ -46,6 +46,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
public void Cleanup()
{
this.bmpStream.Dispose();
this.bmpStream = null;
this.bmpCore.Dispose();
this.bmpDrawing.Dispose();
}
@ -53,19 +54,15 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
[Benchmark(Baseline = true, Description = "System.Drawing Gif")]
public void GifSystemDrawing()
{
using (var memoryStream = new MemoryStream())
{
this.bmpDrawing.Save(memoryStream, ImageFormat.Gif);
}
using var memoryStream = new MemoryStream();
this.bmpDrawing.Save(memoryStream, ImageFormat.Gif);
}
[Benchmark(Description = "ImageSharp Gif")]
public void GifCore()
public void GifImageSharp()
{
using (var memoryStream = new MemoryStream())
{
this.bmpCore.SaveAsGif(memoryStream, this.encoder);
}
using var memoryStream = new MemoryStream();
this.bmpCore.SaveAsGif(memoryStream, this.encoder);
}
}
}

10
tests/ImageSharp.Benchmarks/Codecs/EncodeGifMultiple.cs

@ -10,7 +10,7 @@ using SixLabors.ImageSharp.Processing.Processors.Quantization;
namespace SixLabors.ImageSharp.Benchmarks.Codecs
{
[Config(typeof(Config.ShortClr))]
[Config(typeof(Config.ShortMultiFramework))]
public class EncodeGifMultiple : MultiImageBenchmarkBase.WithImagesPreloaded
{
[Params(InputImageCategory.AllImages)]
@ -20,8 +20,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
[Benchmark(Description = "EncodeGifMultiple - ImageSharp")]
public void EncodeGifImageSharp()
{
this.ForEachImageSharpImage((img, ms) =>
=> this.ForEachImageSharpImage((img, ms) =>
{
// Try to get as close to System.Drawing's output as possible
var options = new GifEncoder
@ -32,16 +31,13 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
img.Save(ms, options);
return null;
});
}
[Benchmark(Baseline = true, Description = "EncodeGifMultiple - System.Drawing")]
public void EncodeGifSystemDrawing()
{
this.ForEachSystemDrawingImage((img, ms) =>
=> this.ForEachSystemDrawingImage((img, ms) =>
{
img.Save(ms, ImageFormat.Gif);
return null;
});
}
}
}

59
tests/ImageSharp.Benchmarks/Codecs/EncodeIndexedPng.cs

@ -8,15 +8,15 @@ using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Processing.Processors.Quantization;
using SixLabors.ImageSharp.Tests;
using CoreImage = SixLabors.ImageSharp.Image;
namespace SixLabors.ImageSharp.Benchmarks.Codecs
{
/// <summary>
/// Benchmarks saving png files using different quantizers. System.Drawing cannot save indexed png files so we cannot compare.
/// Benchmarks saving png files using different quantizers.
/// System.Drawing cannot save indexed png files so we cannot compare.
/// </summary>
[Config(typeof(Config.ShortClr))]
public class EncodeIndexedPng : BenchmarkBase
[Config(typeof(Config.ShortMultiFramework))]
public class EncodeIndexedPng
{
// System.Drawing needs this.
private Stream bmpStream;
@ -28,7 +28,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
if (this.bmpStream == null)
{
this.bmpStream = File.OpenRead(Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, TestImages.Bmp.Car));
this.bmpCore = CoreImage.Load<Rgba32>(this.bmpStream);
this.bmpCore = Image.Load<Rgba32>(this.bmpStream);
this.bmpStream.Position = 0;
}
}
@ -37,67 +37,56 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
public void Cleanup()
{
this.bmpStream.Dispose();
this.bmpStream = null;
this.bmpCore.Dispose();
}
[Benchmark(Baseline = true, Description = "ImageSharp Octree Png")]
public void PngCoreOctree()
{
using (var memoryStream = new MemoryStream())
{
var options = new PngEncoder { Quantizer = KnownQuantizers.Octree };
this.bmpCore.SaveAsPng(memoryStream, options);
}
using var memoryStream = new MemoryStream();
var options = new PngEncoder { Quantizer = KnownQuantizers.Octree };
this.bmpCore.SaveAsPng(memoryStream, options);
}
[Benchmark(Description = "ImageSharp Octree NoDither Png")]
public void PngCoreOctreeNoDither()
{
using (var memoryStream = new MemoryStream())
{
var options = new PngEncoder { Quantizer = new OctreeQuantizer(new QuantizerOptions { Dither = null }) };
this.bmpCore.SaveAsPng(memoryStream, options);
}
using var memoryStream = new MemoryStream();
var options = new PngEncoder { Quantizer = new OctreeQuantizer(new QuantizerOptions { Dither = null }) };
this.bmpCore.SaveAsPng(memoryStream, options);
}
[Benchmark(Description = "ImageSharp Palette Png")]
public void PngCorePalette()
{
using (var memoryStream = new MemoryStream())
{
var options = new PngEncoder { Quantizer = KnownQuantizers.WebSafe };
this.bmpCore.SaveAsPng(memoryStream, options);
}
using var memoryStream = new MemoryStream();
var options = new PngEncoder { Quantizer = KnownQuantizers.WebSafe };
this.bmpCore.SaveAsPng(memoryStream, options);
}
[Benchmark(Description = "ImageSharp Palette NoDither Png")]
public void PngCorePaletteNoDither()
{
using (var memoryStream = new MemoryStream())
{
var options = new PngEncoder { Quantizer = new WebSafePaletteQuantizer(new QuantizerOptions { Dither = null }) };
this.bmpCore.SaveAsPng(memoryStream, options);
}
using var memoryStream = new MemoryStream();
var options = new PngEncoder { Quantizer = new WebSafePaletteQuantizer(new QuantizerOptions { Dither = null }) };
this.bmpCore.SaveAsPng(memoryStream, options);
}
[Benchmark(Description = "ImageSharp Wu Png")]
public void PngCoreWu()
{
using (var memoryStream = new MemoryStream())
{
var options = new PngEncoder { Quantizer = KnownQuantizers.Wu };
this.bmpCore.SaveAsPng(memoryStream, options);
}
using var memoryStream = new MemoryStream();
var options = new PngEncoder { Quantizer = KnownQuantizers.Wu };
this.bmpCore.SaveAsPng(memoryStream, options);
}
[Benchmark(Description = "ImageSharp Wu NoDither Png")]
public void PngCoreWuNoDither()
{
using (var memoryStream = new MemoryStream())
{
var options = new PngEncoder { Quantizer = new WuQuantizer(new QuantizerOptions { Dither = null }) };
this.bmpCore.SaveAsPng(memoryStream, options);
}
using var memoryStream = new MemoryStream();
var options = new PngEncoder { Quantizer = new WuQuantizer(new QuantizerOptions { Dither = null }) };
this.bmpCore.SaveAsPng(memoryStream, options);
}
}
}

19
tests/ImageSharp.Benchmarks/Codecs/EncodePng.cs

@ -11,8 +11,8 @@ using SDImage = System.Drawing.Image;
namespace SixLabors.ImageSharp.Benchmarks.Codecs
{
[Config(typeof(Config.ShortClr))]
public class EncodePng : BenchmarkBase
[Config(typeof(Config.ShortMultiFramework))]
public class EncodePng
{
// System.Drawing needs this.
private Stream bmpStream;
@ -39,6 +39,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
public void Cleanup()
{
this.bmpStream.Dispose();
this.bmpStream = null;
this.bmpCore.Dispose();
this.bmpDrawing.Dispose();
}
@ -46,20 +47,16 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
[Benchmark(Baseline = true, Description = "System.Drawing Png")]
public void PngSystemDrawing()
{
using (var memoryStream = new MemoryStream())
{
this.bmpDrawing.Save(memoryStream, ImageFormat.Png);
}
using var memoryStream = new MemoryStream();
this.bmpDrawing.Save(memoryStream, ImageFormat.Png);
}
[Benchmark(Description = "ImageSharp Png")]
public void PngCore()
{
using (var memoryStream = new MemoryStream())
{
var encoder = new PngEncoder { FilterMethod = PngFilterMethod.None };
this.bmpCore.SaveAsPng(memoryStream, encoder);
}
using var memoryStream = new MemoryStream();
var encoder = new PngEncoder { FilterMethod = PngFilterMethod.None };
this.bmpCore.SaveAsPng(memoryStream, encoder);
}
}
}

34
tests/ImageSharp.Benchmarks/Codecs/EncodeTga.cs

@ -2,23 +2,21 @@
// Licensed under the Apache License, Version 2.0.
using System.IO;
using BenchmarkDotNet.Attributes;
using ImageMagick;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Tests;
namespace SixLabors.ImageSharp.Benchmarks.Codecs
{
[Config(typeof(Config.ShortClr))]
public class EncodeTga : BenchmarkBase
[Config(typeof(Config.ShortMultiFramework))]
public class EncodeTga
{
private MagickImage tgaMagick;
private Image<Rgba32> tgaCore;
private string TestImageFullPath => Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, this.TestImage);
private string TestImageFullPath
=> Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, this.TestImage);
[Params(TestImages.Tga.Bit24BottomLeft)]
public string TestImage { get; set; }
@ -33,22 +31,26 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
}
}
[GlobalCleanup]
public void Cleanup()
{
this.tgaCore.Dispose();
this.tgaCore = null;
this.tgaMagick.Dispose();
}
[Benchmark(Baseline = true, Description = "Magick Tga")]
public void BmpSystemDrawing()
public void BmpImageMagick()
{
using (var memoryStream = new MemoryStream())
{
this.tgaMagick.Write(memoryStream, MagickFormat.Tga);
}
using var memoryStream = new MemoryStream();
this.tgaMagick.Write(memoryStream, MagickFormat.Tga);
}
[Benchmark(Description = "ImageSharp Tga")]
public void BmpCore()
public void BmpImageSharp()
{
using (var memoryStream = new MemoryStream())
{
this.tgaCore.SaveAsBmp(memoryStream);
}
using var memoryStream = new MemoryStream();
this.tgaCore.SaveAsBmp(memoryStream);
}
}
}

32
tests/ImageSharp.Benchmarks/Codecs/GetSetPixel.cs

@ -1,32 +0,0 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System.Drawing;
using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Benchmarks.Codecs
{
public class GetSetPixel : BenchmarkBase
{
[Benchmark(Baseline = true, Description = "System.Drawing GetSet pixel")]
public System.Drawing.Color ResizeSystemDrawing()
{
using (var source = new Bitmap(400, 400))
{
source.SetPixel(200, 200, System.Drawing.Color.White);
return source.GetPixel(200, 200);
}
}
[Benchmark(Description = "ImageSharp GetSet pixel")]
public Rgba32 ResizeCore()
{
using (var image = new Image<Rgba32>(400, 400))
{
image[200, 200] = Color.White;
return image[200, 200];
}
}
}
}

16
tests/ImageSharp.Benchmarks/Codecs/Jpeg/CmykColorConversion.cs

@ -1,4 +1,4 @@
// Copyright (c) Six Labors.
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using BenchmarkDotNet.Attributes;
@ -6,7 +6,7 @@ using SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters;
namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
{
[Config(typeof(Config.ShortClr))]
[Config(typeof(Config.ShortMultiFramework))]
public class CmykColorConversion : ColorConversionBenchmark
{
public CmykColorConversion()
@ -17,25 +17,25 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
[Benchmark(Baseline = true)]
public void Scalar()
{
var values = new JpegColorConverter.ComponentValues(this.input, 0);
var values = new JpegColorConverter.ComponentValues(this.Input, 0);
new JpegColorConverter.FromCmykBasic(8).ConvertToRgba(values, this.output);
new JpegColorConverter.FromCmykBasic(8).ConvertToRgba(values, this.Output);
}
[Benchmark]
public void SimdVector8()
{
var values = new JpegColorConverter.ComponentValues(this.input, 0);
var values = new JpegColorConverter.ComponentValues(this.Input, 0);
new JpegColorConverter.FromCmykVector8(8).ConvertToRgba(values, this.output);
new JpegColorConverter.FromCmykVector8(8).ConvertToRgba(values, this.Output);
}
[Benchmark]
public void SimdVectorAvx2()
{
var values = new JpegColorConverter.ComponentValues(this.input, 0);
var values = new JpegColorConverter.ComponentValues(this.Input, 0);
new JpegColorConverter.FromCmykAvx2(8).ConvertToRgba(values, this.output);
new JpegColorConverter.FromCmykAvx2(8).ConvertToRgba(values, this.Output);
}
}
}

20
tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversionBenchmark.cs

@ -1,4 +1,4 @@
// Copyright (c) Six Labors.
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System;
@ -11,27 +11,27 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
public abstract class ColorConversionBenchmark
{
private readonly int componentCount;
protected Buffer2D<float>[] input;
protected Vector4[] output;
public const int Count = 128;
protected ColorConversionBenchmark(int componentCount)
{
this.componentCount = componentCount;
}
=> this.componentCount = componentCount;
public const int Count = 128;
protected Buffer2D<float>[] Input { get; private set; }
protected Vector4[] Output { get; private set; }
[GlobalSetup]
public void Setup()
{
this.input = CreateRandomValues(this.componentCount, Count);
this.output = new Vector4[Count];
this.Input = CreateRandomValues(this.componentCount, Count);
this.Output = new Vector4[Count];
}
[GlobalCleanup]
public void Cleanup()
{
foreach (Buffer2D<float> buffer in this.input)
foreach (Buffer2D<float> buffer in this.Input)
{
buffer.Dispose();
}

7
tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpegParseStreamOnly.cs

@ -3,7 +3,6 @@
using System.IO;
using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.IO;
using SixLabors.ImageSharp.Tests;
@ -11,7 +10,7 @@ using SDSize = System.Drawing.Size;
namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
{
[Config(typeof(Config.ShortClr))]
[Config(typeof(Config.ShortMultiFramework))]
public class DecodeJpegParseStreamOnly
{
[Params(TestImages.Jpeg.BenchmarkSuite.Lake_Small444YCbCr)]
@ -23,9 +22,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
[GlobalSetup]
public void Setup()
{
this.jpegBytes = File.ReadAllBytes(this.TestImageFullPath);
}
=> this.jpegBytes = File.ReadAllBytes(this.TestImageFullPath);
[Benchmark(Baseline = true, Description = "System.Drawing FULL")]
public SDSize JpegSystemDrawing()

16
tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpeg_Aggregate.cs

@ -2,22 +2,20 @@
// Licensed under the Apache License, Version 2.0.
using System.Collections.Generic;
using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Tests;
using SDImage = System.Drawing.Image;
// ReSharper disable InconsistentNaming
namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
{
/// <summary>
/// An expensive Jpeg benchmark, running on a wide range of input images, showing aggregate results.
/// An expensive Jpeg benchmark, running on a wide range of input images,
/// showing aggregate results.
/// </summary>
[Config(typeof(MultiImageBenchmarkBase.Config))]
[Config(typeof(Config.ShortMultiFramework))]
public class DecodeJpeg_Aggregate : MultiImageBenchmarkBase
{
protected override IEnumerable<string> InputImageSubfoldersOrFiles =>
@ -35,14 +33,10 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
[Benchmark]
public void ImageSharp()
{
this.ForEachStream(ms => Image.Load<Rgba32>(ms, new JpegDecoder()));
}
=> this.ForEachStream(ms => Image.Load<Rgba32>(ms, new JpegDecoder()));
[Benchmark(Baseline = true)]
public void SystemDrawing()
{
this.ForEachStream(SDImage.FromStream);
}
=> this.ForEachStream(SDImage.FromStream);
}
}

20
tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpeg_ImageSpecific.cs

@ -3,11 +3,6 @@
using System.IO;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Diagnosers;
using BenchmarkDotNet.Environments;
using BenchmarkDotNet.Jobs;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Tests;
@ -20,22 +15,9 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
/// <summary>
/// Image-specific Jpeg benchmarks
/// </summary>
[Config(typeof(Config.ShortClr))]
[Config(typeof(Config.ShortMultiFramework))]
public class DecodeJpeg_ImageSpecific
{
public class Config : ManualConfig
{
public Config() => this.AddDiagnoser(MemoryDiagnoser.Default);
public class ShortClr : Benchmarks.Config
{
public ShortClr() =>
// Job.Default.With(ClrRuntime.Net472).WithLaunchCount(1).WithWarmupCount(2).WithIterationCount(3),
this.AddJob(Job.Default.WithRuntime(CoreRuntime.Core31).WithLaunchCount(1).WithWarmupCount(2).WithIterationCount(3));
}
}
private byte[] jpegBytes;
private string TestImageFullPath => Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, this.TestImage);

32
tests/ImageSharp.Benchmarks/Codecs/Jpeg/EncodeJpeg.cs

@ -1,23 +1,20 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System.Drawing.Imaging;
using System.IO;
using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Tests;
using SDImage = System.Drawing.Image;
namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
{
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using SixLabors.ImageSharp.Tests;
using CoreImage = SixLabors.ImageSharp.Image;
public class EncodeJpeg : BenchmarkBase
public class EncodeJpeg
{
// System.Drawing needs this.
private Stream bmpStream;
private Image bmpDrawing;
private SDImage bmpDrawing;
private Image<Rgba32> bmpCore;
[GlobalSetup]
@ -27,9 +24,9 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
{
const string TestImage = TestImages.Bmp.Car;
this.bmpStream = File.OpenRead(Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, TestImage));
this.bmpCore = CoreImage.Load<Rgba32>(this.bmpStream);
this.bmpCore = Image.Load<Rgba32>(this.bmpStream);
this.bmpStream.Position = 0;
this.bmpDrawing = Image.FromStream(this.bmpStream);
this.bmpDrawing = SDImage.FromStream(this.bmpStream);
}
}
@ -37,6 +34,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
public void Cleanup()
{
this.bmpStream.Dispose();
this.bmpStream = null;
this.bmpCore.Dispose();
this.bmpDrawing.Dispose();
}
@ -44,19 +42,15 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
[Benchmark(Baseline = true, Description = "System.Drawing Jpeg")]
public void JpegSystemDrawing()
{
using (var stream = new MemoryStream())
{
this.bmpDrawing.Save(stream, ImageFormat.Jpeg);
}
using var stream = new MemoryStream();
this.bmpDrawing.Save(stream, ImageFormat.Jpeg);
}
[Benchmark(Description = "ImageSharp Jpeg")]
public void JpegCore()
{
using (var stream = new MemoryStream())
{
this.bmpCore.SaveAsJpeg(stream);
}
using var stream = new MemoryStream();
this.bmpCore.SaveAsJpeg(stream);
}
}
}

10
tests/ImageSharp.Benchmarks/Codecs/Jpeg/EncodeJpegMultiple.cs

@ -8,7 +8,7 @@ using SixLabors.ImageSharp.Formats.Jpeg;
namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
{
[Config(typeof(Config.ShortClr))] // It's long enough to iterate through multiple files
[Config(typeof(Config.ShortMultiFramework))]
public class EncodeJpegMultiple : MultiImageBenchmarkBase.WithImagesPreloaded
{
protected override IEnumerable<string> InputImageSubfoldersOrFiles => new[] { "Bmp/", "Jpg/baseline" };
@ -17,22 +17,18 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
[Benchmark(Description = "EncodeJpegMultiple - ImageSharp")]
public void EncodeJpegImageSharp()
{
this.ForEachImageSharpImage((img, ms) =>
=> this.ForEachImageSharpImage((img, ms) =>
{
img.Save(ms, new JpegEncoder());
return null;
});
}
[Benchmark(Baseline = true, Description = "EncodeJpegMultiple - System.Drawing")]
public void EncodeJpegSystemDrawing()
{
this.ForEachSystemDrawingImage((img, ms) =>
=> this.ForEachSystemDrawingImage((img, ms) =>
{
img.Save(ms, ImageFormat.Jpeg);
return null;
});
}
}
}

10
tests/ImageSharp.Benchmarks/Codecs/Jpeg/GrayscaleColorConversion.cs

@ -6,7 +6,7 @@ using SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters;
namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
{
[Config(typeof(Config.ShortClr))]
[Config(typeof(Config.ShortMultiFramework))]
public class GrayscaleColorConversion : ColorConversionBenchmark
{
public GrayscaleColorConversion()
@ -17,17 +17,17 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
[Benchmark(Baseline = true)]
public void Scalar()
{
var values = new JpegColorConverter.ComponentValues(this.input, 0);
var values = new JpegColorConverter.ComponentValues(this.Input, 0);
new JpegColorConverter.FromGrayscaleBasic(8).ConvertToRgba(values, this.output);
new JpegColorConverter.FromGrayscaleBasic(8).ConvertToRgba(values, this.Output);
}
[Benchmark]
public void SimdVectorAvx2()
{
var values = new JpegColorConverter.ComponentValues(this.input, 0);
var values = new JpegColorConverter.ComponentValues(this.Input, 0);
new JpegColorConverter.FromGrayscaleAvx2(8).ConvertToRgba(values, this.output);
new JpegColorConverter.FromGrayscaleAvx2(8).ConvertToRgba(values, this.Output);
}
}
}

13
tests/ImageSharp.Benchmarks/Codecs/Jpeg/IdentifyJpeg.cs

@ -1,15 +1,14 @@
// Copyright (c) Six Labors.
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System.IO;
using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.Tests;
namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
{
[Config(typeof(Config.ShortClr))]
[Config(typeof(Config.ShortMultiFramework))]
public class IdentifyJpeg
{
private byte[] jpegBytes;
@ -31,11 +30,9 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
[Benchmark]
public IImageInfo Identify()
{
using (var memoryStream = new MemoryStream(this.jpegBytes))
{
var decoder = new JpegDecoder();
return decoder.Identify(Configuration.Default, memoryStream);
}
using var memoryStream = new MemoryStream(this.jpegBytes);
var decoder = new JpegDecoder();
return decoder.Identify(Configuration.Default, memoryStream);
}
}
}

64
tests/ImageSharp.Benchmarks/Codecs/Jpeg/LoadResizeSave_Aggregate.cs

@ -6,9 +6,7 @@ using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
@ -17,7 +15,7 @@ using SixLabors.ImageSharp.Tests;
// ReSharper disable InconsistentNaming
namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
{
[Config(typeof(MultiImageBenchmarkBase.Config))]
[Config(typeof(Config.ShortMultiFramework))]
public class LoadResizeSave_Aggregate : MultiImageBenchmarkBase
{
protected override IEnumerable<string> InputImageSubfoldersOrFiles =>
@ -48,49 +46,43 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
[Benchmark(Baseline = true)]
public void SystemDrawing()
{
this.ForEachStream(
=> this.ForEachStream(
sourceStream =>
{
using (var destStream = new MemoryStream(this.destBytes))
using (var source = System.Drawing.Image.FromStream(sourceStream))
using (var destination = new Bitmap(source.Width / 4, source.Height / 4))
{
using (var destStream = new MemoryStream(this.destBytes))
using (var source = System.Drawing.Image.FromStream(sourceStream))
using (var destination = new Bitmap(source.Width / 4, source.Height / 4))
using (var g = Graphics.FromImage(destination))
{
using (var g = Graphics.FromImage(destination))
{
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.CompositingQuality = CompositingQuality.HighQuality;
g.DrawImage(source, 0, 0, 400, 400);
}
destination.Save(destStream, ImageFormat.Jpeg);
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.CompositingQuality = CompositingQuality.HighQuality;
g.DrawImage(source, 0, 0, 400, 400);
}
return null;
});
}
destination.Save(destStream, ImageFormat.Jpeg);
}
return null;
});
[Benchmark]
public void ImageSharp()
{
this.ForEachStream(
=> this.ForEachStream(
sourceStream =>
{
using (var source = Image.Load<Rgba32>(
this.configuration,
sourceStream,
new JpegDecoder { IgnoreMetadata = true }))
{
using (var source = Image.Load<Rgba32>(
this.configuration,
sourceStream,
new JpegDecoder { IgnoreMetadata = true }))
{
using (var destStream = new MemoryStream(this.destBytes))
{
source.Mutate(c => c.Resize(source.Width / 4, source.Height / 4));
source.SaveAsJpeg(destStream);
}
}
using var destStream = new MemoryStream(this.destBytes);
source.Mutate(c => c.Resize(source.Width / 4, source.Height / 4));
source.SaveAsJpeg(destStream);
}
return null;
});
}
return null;
});
}
}

32
tests/ImageSharp.Benchmarks/Codecs/Jpeg/LoadResizeSave_ImageSpecific.cs

@ -7,17 +7,15 @@ using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Tests;
using SDImage = System.Drawing.Image;
// ReSharper disable InconsistentNaming
namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
{
[Config(typeof(Config.ShortClr))]
[Config(typeof(Config.ShortMultiFramework))]
public class LoadResizeSave_ImageSpecific
{
private readonly Configuration configuration = new Configuration(new JpegConfigurationModule());
@ -32,6 +30,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
TestImages.Jpeg.BenchmarkSuite.Lake_Small444YCbCr,
TestImages.Jpeg.BenchmarkSuite.BadRstProgressive518_Large444YCbCr,
TestImages.Jpeg.BenchmarkSuite.Jpeg420Exif_MidSizeYCbCr)]
public string TestImage { get; set; }
[Params(false, true)]
@ -51,28 +50,25 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
[Benchmark(Baseline = true)]
public void SystemDrawing()
{
using (var sourceStream = new MemoryStream(this.sourceBytes))
using (var destStream = new MemoryStream(this.destBytes))
using (var source = SDImage.FromStream(sourceStream))
using (var destination = new Bitmap(source.Width / 4, source.Height / 4))
using var sourceStream = new MemoryStream(this.sourceBytes);
using var destStream = new MemoryStream(this.destBytes);
using var source = SDImage.FromStream(sourceStream);
using var destination = new Bitmap(source.Width / 4, source.Height / 4);
using (var g = Graphics.FromImage(destination))
{
using (var g = Graphics.FromImage(destination))
{
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.CompositingQuality = CompositingQuality.HighQuality;
g.DrawImage(source, 0, 0, 400, 400);
}
destination.Save(destStream, ImageFormat.Jpeg);
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.CompositingQuality = CompositingQuality.HighQuality;
g.DrawImage(source, 0, 0, 400, 400);
}
destination.Save(destStream, ImageFormat.Jpeg);
}
[Benchmark]
public void ImageSharp()
{
var source = Image.Load(this.configuration, this.sourceBytes, new JpegDecoder { IgnoreMetadata = true });
using (source)
using (var source = Image.Load(this.configuration, this.sourceBytes, new JpegDecoder { IgnoreMetadata = true }))
using (var destStream = new MemoryStream(this.destBytes))
{
source.Mutate(c => c.Resize(source.Width / 4, source.Height / 4));

14
tests/ImageSharp.Benchmarks/Codecs/Jpeg/RgbColorConversion.cs

@ -6,7 +6,7 @@ using SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters;
namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
{
[Config(typeof(Config.ShortClr))]
[Config(typeof(Config.ShortMultiFramework))]
public class RgbColorConversion : ColorConversionBenchmark
{
public RgbColorConversion()
@ -17,25 +17,25 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
[Benchmark(Baseline = true)]
public void Scalar()
{
var values = new JpegColorConverter.ComponentValues(this.input, 0);
var values = new JpegColorConverter.ComponentValues(this.Input, 0);
new JpegColorConverter.FromRgbBasic(8).ConvertToRgba(values, this.output);
new JpegColorConverter.FromRgbBasic(8).ConvertToRgba(values, this.Output);
}
[Benchmark]
public void SimdVector8()
{
var values = new JpegColorConverter.ComponentValues(this.input, 0);
var values = new JpegColorConverter.ComponentValues(this.Input, 0);
new JpegColorConverter.FromRgbVector8(8).ConvertToRgba(values, this.output);
new JpegColorConverter.FromRgbVector8(8).ConvertToRgba(values, this.Output);
}
[Benchmark]
public void SimdVectorAvx2()
{
var values = new JpegColorConverter.ComponentValues(this.input, 0);
var values = new JpegColorConverter.ComponentValues(this.Input, 0);
new JpegColorConverter.FromRgbAvx2(8).ConvertToRgba(values, this.output);
new JpegColorConverter.FromRgbAvx2(8).ConvertToRgba(values, this.Output);
}
}
}

19
tests/ImageSharp.Benchmarks/Codecs/Jpeg/YCbCrColorConversion.cs

@ -2,12 +2,11 @@
// Licensed under the Apache License, Version 2.0.
using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters;
namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
{
[Config(typeof(Config.ShortClr))]
[Config(typeof(Config.ShortMultiFramework))]
public class YCbCrColorConversion : ColorConversionBenchmark
{
public YCbCrColorConversion()
@ -18,33 +17,33 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
[Benchmark]
public void Scalar()
{
var values = new JpegColorConverter.ComponentValues(this.input, 0);
var values = new JpegColorConverter.ComponentValues(this.Input, 0);
new JpegColorConverter.FromYCbCrBasic(8).ConvertToRgba(values, this.output);
new JpegColorConverter.FromYCbCrBasic(8).ConvertToRgba(values, this.Output);
}
[Benchmark(Baseline = true)]
public void SimdVector()
{
var values = new JpegColorConverter.ComponentValues(this.input, 0);
var values = new JpegColorConverter.ComponentValues(this.Input, 0);
new JpegColorConverter.FromYCbCrVector4(8).ConvertToRgba(values, this.output);
new JpegColorConverter.FromYCbCrVector4(8).ConvertToRgba(values, this.Output);
}
[Benchmark]
public void SimdVector8()
{
var values = new JpegColorConverter.ComponentValues(this.input, 0);
var values = new JpegColorConverter.ComponentValues(this.Input, 0);
new JpegColorConverter.FromYCbCrVector8(8).ConvertToRgba(values, this.output);
new JpegColorConverter.FromYCbCrVector8(8).ConvertToRgba(values, this.Output);
}
[Benchmark]
public void SimdVectorAvx2()
{
var values = new JpegColorConverter.ComponentValues(this.input, 0);
var values = new JpegColorConverter.ComponentValues(this.Input, 0);
new JpegColorConverter.FromYCbCrAvx2(8).ConvertToRgba(values, this.output);
new JpegColorConverter.FromYCbCrAvx2(8).ConvertToRgba(values, this.Output);
}
}
}

14
tests/ImageSharp.Benchmarks/Codecs/Jpeg/YccKColorConverter.cs

@ -6,7 +6,7 @@ using SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters;
namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
{
[Config(typeof(Config.ShortClr))]
[Config(typeof(Config.ShortMultiFramework))]
public class YccKColorConverter : ColorConversionBenchmark
{
public YccKColorConverter()
@ -17,25 +17,25 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
[Benchmark(Baseline = true)]
public void Scalar()
{
var values = new JpegColorConverter.ComponentValues(this.input, 0);
var values = new JpegColorConverter.ComponentValues(this.Input, 0);
new JpegColorConverter.FromYccKBasic(8).ConvertToRgba(values, this.output);
new JpegColorConverter.FromYccKBasic(8).ConvertToRgba(values, this.Output);
}
[Benchmark]
public void SimdVector8()
{
var values = new JpegColorConverter.ComponentValues(this.input, 0);
var values = new JpegColorConverter.ComponentValues(this.Input, 0);
new JpegColorConverter.FromYccKVector8(8).ConvertToRgba(values, this.output);
new JpegColorConverter.FromYccKVector8(8).ConvertToRgba(values, this.Output);
}
[Benchmark]
public void SimdVectorAvx2()
{
var values = new JpegColorConverter.ComponentValues(this.input, 0);
var values = new JpegColorConverter.ComponentValues(this.Input, 0);
new JpegColorConverter.FromYccKAvx2(8).ConvertToRgba(values, this.output);
new JpegColorConverter.FromYccKAvx2(8).ConvertToRgba(values, this.Output);
}
}
}

112
tests/ImageSharp.Benchmarks/Codecs/MultiImageBenchmarkBase.cs

@ -8,33 +8,18 @@ using System.IO;
using System.Linq;
using System.Numerics;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Diagnosers;
using BenchmarkDotNet.Environments;
using BenchmarkDotNet.Jobs;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Tests;
using CoreImage = SixLabors.ImageSharp.Image;
namespace SixLabors.ImageSharp.Benchmarks.Codecs
{
public abstract class MultiImageBenchmarkBase
{
public class Config : ManualConfig
{
public Config() => this.AddDiagnoser(MemoryDiagnoser.Default);
public class ShortClr : Benchmarks.Config
{
public ShortClr() => this.AddJob(Job.Default.WithRuntime(CoreRuntime.Core21).WithLaunchCount(1).WithWarmupCount(1).WithIterationCount(2));
}
}
protected Dictionary<string, byte[]> FileNamesToBytes { get; set; } = new Dictionary<string, byte[]>();
protected Dictionary<string, Image<Rgba32>> FileNamesToImageSharpImages { get; set; } = new Dictionary<string, Image<Rgba32>>();
protected Dictionary<string, Bitmap> FileNamesToSystemDrawingImages { get; set; } = new Dictionary<string, System.Drawing.Bitmap>();
protected Dictionary<string, Bitmap> FileNamesToSystemDrawingImages { get; set; } = new Dictionary<string, Bitmap>();
/// <summary>
/// The values of this enum separate input files into categories.
@ -72,7 +57,8 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
/// <summary>
/// Gets folders containing files OR files to be processed by the benchmark.
/// </summary>
protected IEnumerable<string> AllFoldersOrFiles => this.InputImageSubfoldersOrFiles.Select(f => Path.Combine(this.BaseFolder, f));
protected IEnumerable<string> AllFoldersOrFiles
=> this.InputImageSubfoldersOrFiles.Select(f => Path.Combine(this.BaseFolder, f));
/// <summary>
/// Gets the large image threshold.
@ -83,19 +69,13 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
protected IEnumerable<KeyValuePair<string, T>> EnumeratePairsByBenchmarkSettings<T>(
Dictionary<string, T> input,
Predicate<T> checkIfSmall)
{
switch (this.InputCategory)
=> this.InputCategory switch
{
case InputImageCategory.AllImages:
return input;
case InputImageCategory.SmallImagesOnly:
return input.Where(kv => checkIfSmall(kv.Value));
case InputImageCategory.LargeImagesOnly:
return input.Where(kv => !checkIfSmall(kv.Value));
default:
throw new ArgumentOutOfRangeException();
}
}
InputImageCategory.AllImages => input,
InputImageCategory.SmallImagesOnly => input.Where(kv => checkIfSmall(kv.Value)),
InputImageCategory.LargeImagesOnly => input.Where(kv => !checkIfSmall(kv.Value)),
_ => throw new ArgumentOutOfRangeException(),
};
protected IEnumerable<KeyValuePair<string, byte[]>> FileNames2Bytes
=>
@ -150,17 +130,15 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
{
foreach (KeyValuePair<string, byte[]> kv in this.FileNames2Bytes)
{
using (var memoryStream = new MemoryStream(kv.Value))
using var memoryStream = new MemoryStream(kv.Value);
try
{
try
{
object obj = operation(memoryStream);
(obj as IDisposable)?.Dispose();
}
catch (Exception ex)
{
Console.WriteLine($"Operation on {kv.Key} failed with {ex.Message}");
}
object obj = operation(memoryStream);
(obj as IDisposable)?.Dispose();
}
catch (Exception ex)
{
Console.WriteLine($"Operation on {kv.Key} failed with {ex.Message}");
}
}
}
@ -178,7 +156,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
using (var ms1 = new MemoryStream(bytes))
{
this.FileNamesToImageSharpImages[fn] = CoreImage.Load<Rgba32>(ms1);
this.FileNamesToImageSharpImages[fn] = Image.Load<Rgba32>(ms1);
}
this.FileNamesToSystemDrawingImages[fn] = new Bitmap(new MemoryStream(bytes));
@ -191,7 +169,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
this.FileNamesToImageSharpImages,
img => img.Width * img.Height < this.LargeImageThresholdInPixels);
protected IEnumerable<KeyValuePair<string, System.Drawing.Bitmap>> FileNames2SystemDrawingImages
protected IEnumerable<KeyValuePair<string, Bitmap>> FileNames2SystemDrawingImages
=>
this.EnumeratePairsByBenchmarkSettings(
this.FileNamesToSystemDrawingImages,
@ -217,22 +195,20 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
protected void ForEachImageSharpImage(Func<Image<Rgba32>, MemoryStream, object> operation)
{
using (var workStream = new MemoryStream())
{
this.ForEachImageSharpImage(
img =>
{
// ReSharper disable AccessToDisposedClosure
object result = operation(img, workStream);
workStream.Seek(0, SeekOrigin.Begin);
// ReSharper restore AccessToDisposedClosure
return result;
});
}
using var workStream = new MemoryStream();
this.ForEachImageSharpImage(
img =>
{
// ReSharper disable AccessToDisposedClosure
object result = operation(img, workStream);
workStream.Seek(0, SeekOrigin.Begin);
// ReSharper restore AccessToDisposedClosure
return result;
});
}
protected void ForEachSystemDrawingImage(Func<System.Drawing.Bitmap, object> operation)
protected void ForEachSystemDrawingImage(Func<Bitmap, object> operation)
{
foreach (KeyValuePair<string, Bitmap> kv in this.FileNames2SystemDrawingImages)
{
@ -248,21 +224,19 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
}
}
protected void ForEachSystemDrawingImage(Func<System.Drawing.Bitmap, MemoryStream, object> operation)
protected void ForEachSystemDrawingImage(Func<Bitmap, MemoryStream, object> operation)
{
using (var workStream = new MemoryStream())
{
this.ForEachSystemDrawingImage(
img =>
{
// ReSharper disable AccessToDisposedClosure
object result = operation(img, workStream);
workStream.Seek(0, SeekOrigin.Begin);
// ReSharper restore AccessToDisposedClosure
return result;
});
}
using var workStream = new MemoryStream();
this.ForEachSystemDrawingImage(
img =>
{
// ReSharper disable AccessToDisposedClosure
object result = operation(img, workStream);
workStream.Seek(0, SeekOrigin.Begin);
// ReSharper restore AccessToDisposedClosure
return result;
});
}
}
}

2
tests/ImageSharp.Benchmarks/Color/Bulk/FromVector4_Rgb24.cs

@ -6,7 +6,7 @@ using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk
{
[Config(typeof(Config.ShortClr))]
[Config(typeof(Config.ShortMultiFramework))]
public class FromVector4_Rgb24 : FromVector4<Rgb24>
{
}

2
tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4_Bgra32.cs

@ -8,7 +8,7 @@ using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk
{
[Config(typeof(Config.ShortClr))]
[Config(typeof(Config.ShortMultiFramework))]
public class ToVector4_Bgra32 : ToVector4<Bgra32>
{
[Benchmark(Baseline = true)]

2
tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4_Rgb24.cs

@ -8,7 +8,7 @@ using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk
{
[Config(typeof(Config.ShortClr))]
[Config(typeof(Config.ShortMultiFramework))]
public class ToVector4_Rgb24 : ToVector4<Rgb24>
{
[Benchmark(Baseline = true)]

8
tests/ImageSharp.Benchmarks/Config.cs

@ -35,12 +35,12 @@ namespace SixLabors.ImageSharp.Benchmarks
Job.Default.WithRuntime(CoreRuntime.Core31));
}
public class ShortClr : Config
public class ShortMultiFramework : Config
{
public ShortClr() => this.AddJob(
public ShortMultiFramework() => this.AddJob(
Job.Default.WithRuntime(ClrRuntime.Net472).WithLaunchCount(1).WithWarmupCount(3).WithIterationCount(3),
Job.Default.WithRuntime(CoreRuntime.Core31).WithLaunchCount(1).WithWarmupCount(3).WithIterationCount(3),
Job.Default.WithRuntime(CoreRuntime.Core21).WithLaunchCount(1).WithWarmupCount(3).WithIterationCount(3));
Job.Default.WithRuntime(CoreRuntime.Core21).WithLaunchCount(1).WithWarmupCount(3).WithIterationCount(3),
Job.Default.WithRuntime(CoreRuntime.Core31).WithLaunchCount(1).WithWarmupCount(3).WithIterationCount(3));
}
public class ShortCore31 : Config

2
tests/ImageSharp.Benchmarks/General/Adler32Benchmark.cs

@ -8,7 +8,7 @@ using SharpAdler32 = ICSharpCode.SharpZipLib.Checksum.Adler32;
namespace SixLabors.ImageSharp.Benchmarks.General
{
[Config(typeof(Config.ShortClr))]
[Config(typeof(Config.ShortMultiFramework))]
public class Adler32Benchmark
{
private byte[] data;

2
tests/ImageSharp.Benchmarks/General/CopyBuffers.cs

@ -16,7 +16,7 @@ namespace SixLabors.ImageSharp.Benchmarks.General
/// - Span.CopyTo() has terrible performance on classic .NET Framework
/// - Buffer.MemoryCopy() performance is good enough for all sizes (but needs pinning)
/// </summary>
[Config(typeof(Config.ShortClr))]
[Config(typeof(Config.ShortMultiFramework))]
public class CopyBuffers
{
private byte[] destArray;

2
tests/ImageSharp.Benchmarks/General/Crc32Benchmark.cs

@ -8,7 +8,7 @@ using SharpCrc32 = ICSharpCode.SharpZipLib.Checksum.Crc32;
namespace SixLabors.ImageSharp.Benchmarks.General
{
[Config(typeof(Config.ShortClr))]
[Config(typeof(Config.ShortMultiFramework))]
public class Crc32Benchmark
{
private byte[] data;

28
tests/ImageSharp.Benchmarks/General/GetSetPixel.cs

@ -0,0 +1,28 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System.Drawing;
using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Benchmarks
{
public class GetSetPixel
{
[Benchmark(Baseline = true, Description = "System.Drawing GetSet pixel")]
public System.Drawing.Color GetSetSystemDrawing()
{
using var source = new Bitmap(400, 400);
source.SetPixel(200, 200, System.Drawing.Color.White);
return source.GetPixel(200, 200);
}
[Benchmark(Description = "ImageSharp GetSet pixel")]
public Rgba32 GetSetImageSharp()
{
using var image = new Image<Rgba32>(400, 400);
image[200, 200] = Color.White;
return image[200, 200];
}
}
}

2
tests/ImageSharp.Benchmarks/General/IO/BufferedStreams.cs

@ -8,7 +8,7 @@ using SixLabors.ImageSharp.IO;
namespace SixLabors.ImageSharp.Benchmarks.IO
{
[Config(typeof(Config.ShortClr))]
[Config(typeof(Config.ShortMultiFramework))]
public class BufferedStreams
{
private readonly byte[] buffer = CreateTestBytes();

2
tests/ImageSharp.Benchmarks/General/Vectorization/UInt32ToSingle.cs

@ -8,7 +8,7 @@ using BenchmarkDotNet.Attributes;
namespace SixLabors.ImageSharp.Benchmarks.General.Vectorization
{
[Config(typeof(Config.ShortClr))]
[Config(typeof(Config.ShortMultiFramework))]
public class UInt32ToSingle
{
private float[] data;

2
tests/ImageSharp.Benchmarks/General/Vectorization/WidenBytesToUInt32.cs

@ -10,7 +10,7 @@ using SixLabors.ImageSharp.Tuples;
namespace SixLabors.ImageSharp.Benchmarks.General.Vectorization
{
[Config(typeof(Config.ShortClr))]
[Config(typeof(Config.ShortMultiFramework))]
public class WidenBytesToUInt32
{
private byte[] source;

2
tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj

@ -43,7 +43,7 @@
<Compile Remove="General\BasicMath\ModuloPowerOfTwoConstant.cs" />
<Compile Remove="General\BasicMath\ModuloPowerOfTwoVariable.cs" />
<Compile Remove="PixelBlenders\**" />
<Compile Remove="Samplers\Resize.cs" />
<Compile Remove="Processing\Resize.cs" />
</ItemGroup>
</Project>

86
tests/ImageSharp.Benchmarks/PixelBlenders/PorterDuffBulkVsPixel.cs

@ -1,21 +1,17 @@
// Copyright (c) Six Labors.
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using System.Numerics;
using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.PixelFormats.PixelBlenders;
namespace SixLabors.ImageSharp.Benchmarks
{
using CoreSize = SixLabors.ImageSharp.Size;
public class PorterDuffBulkVsPixel : BenchmarkBase
public class PorterDuffBulkVsPixel
{
private Configuration Configuration => Configuration.Default;
@ -30,23 +26,21 @@ namespace SixLabors.ImageSharp.Benchmarks
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (IMemoryOwner<Vector4> buffer =
Configuration.Default.MemoryAllocator.Allocate<Vector4>(destination.Length * 3))
{
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
Span<Vector4> sourceSpan = buffer.Slice(destination.Length * 2, destination.Length);
using IMemoryOwner<Vector4> buffer =
Configuration.Default.MemoryAllocator.Allocate<Vector4>(destination.Length * 3);
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
Span<Vector4> sourceSpan = buffer.Slice(destination.Length * 2, destination.Length);
PixelOperations<TPixel>.Instance.ToVector4(this.Configuration, background, backgroundSpan);
PixelOperations<TPixel>.Instance.ToVector4(this.Configuration, source, sourceSpan);
PixelOperations<TPixel>.Instance.ToVector4(this.Configuration, background, backgroundSpan);
PixelOperations<TPixel>.Instance.ToVector4(this.Configuration, source, sourceSpan);
for (int i = 0; i < destination.Length; i++)
{
destinationSpan[i] = PorterDuffFunctions.NormalSrcOver(backgroundSpan[i], sourceSpan[i], amount[i]);
}
PixelOperations<TPixel>.Instance.FromVector4Destructive(this.Configuration, destinationSpan, destination);
for (int i = 0; i < destination.Length; i++)
{
destinationSpan[i] = PorterDuffFunctions.NormalSrcOver(backgroundSpan[i], sourceSpan[i], amount[i]);
}
PixelOperations<TPixel>.Instance.FromVector4Destructive(this.Configuration, destinationSpan, destination);
}
private void BulkPixelConvert<TPixel>(
@ -67,44 +61,36 @@ namespace SixLabors.ImageSharp.Benchmarks
}
[Benchmark(Description = "ImageSharp BulkVectorConvert")]
public CoreSize BulkVectorConvert()
public Size BulkVectorConvert()
{
using (var image = new Image<Rgba32>(800, 800))
{
using (IMemoryOwner<float> amounts = Configuration.Default.MemoryAllocator.Allocate<float>(image.Width))
{
amounts.GetSpan().Fill(1);
using var image = new Image<Rgba32>(800, 800);
using IMemoryOwner<float> amounts = Configuration.Default.MemoryAllocator.Allocate<float>(image.Width);
amounts.GetSpan().Fill(1);
Buffer2D<Rgba32> pixels = image.GetRootFramePixelBuffer();
for (int y = 0; y < image.Height; y++)
{
Span<Rgba32> span = pixels.GetRowSpan(y);
this.BulkVectorConvert(span, span, span, amounts.GetSpan());
}
return new CoreSize(image.Width, image.Height);
}
Buffer2D<Rgba32> pixels = image.GetRootFramePixelBuffer();
for (int y = 0; y < image.Height; y++)
{
Span<Rgba32> span = pixels.GetRowSpan(y);
this.BulkVectorConvert(span, span, span, amounts.GetSpan());
}
return new Size(image.Width, image.Height);
}
[Benchmark(Description = "ImageSharp BulkPixelConvert")]
public CoreSize BulkPixelConvert()
public Size BulkPixelConvert()
{
using (var image = new Image<Rgba32>(800, 800))
using var image = new Image<Rgba32>(800, 800);
using IMemoryOwner<float> amounts = Configuration.Default.MemoryAllocator.Allocate<float>(image.Width);
amounts.GetSpan().Fill(1);
Buffer2D<Rgba32> pixels = image.GetRootFramePixelBuffer();
for (int y = 0; y < image.Height; y++)
{
using (IMemoryOwner<float> amounts = Configuration.Default.MemoryAllocator.Allocate<float>(image.Width))
{
amounts.GetSpan().Fill(1);
Buffer2D<Rgba32> pixels = image.GetRootFramePixelBuffer();
for (int y = 0; y < image.Height; y++)
{
Span<Rgba32> span = pixels.GetRowSpan(y);
this.BulkPixelConvert(span, span, span, amounts.GetSpan());
}
return new CoreSize(image.Width, image.Height);
}
Span<Rgba32> span = pixels.GetRowSpan(y);
this.BulkPixelConvert(span, span, span, amounts.GetSpan());
}
return new Size(image.Width, image.Height);
}
}
}
}

8
tests/ImageSharp.Benchmarks/Samplers/BokehBlur.cs → tests/ImageSharp.Benchmarks/Processing/BokehBlur.cs

@ -5,7 +5,7 @@ using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
namespace SixLabors.ImageSharp.Benchmarks.Samplers
namespace SixLabors.ImageSharp.Benchmarks.Processing
{
[Config(typeof(Config.MultiFramework))]
public class BokehBlur
@ -13,10 +13,8 @@ namespace SixLabors.ImageSharp.Benchmarks.Samplers
[Benchmark]
public void Blur()
{
using (var image = new Image<Rgba32>(Configuration.Default, 400, 400, Color.White))
{
image.Mutate(c => c.BokehBlur());
}
using var image = new Image<Rgba32>(Configuration.Default, 400, 400, Color.White);
image.Mutate(c => c.BokehBlur());
}
}
}

40
tests/ImageSharp.Benchmarks/Processing/Crop.cs

@ -0,0 +1,40 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System.Drawing;
using System.Drawing.Drawing2D;
using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using SDRectangle = System.Drawing.Rectangle;
using SDSize = System.Drawing.Size;
namespace SixLabors.ImageSharp.Benchmarks.Processing
{
[Config(typeof(Config.MultiFramework))]
public class Crop
{
[Benchmark(Baseline = true, Description = "System.Drawing Crop")]
public SDSize CropSystemDrawing()
{
using var source = new Bitmap(800, 800);
using var destination = new Bitmap(100, 100);
using var graphics = Graphics.FromImage(destination);
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.DrawImage(source, new SDRectangle(0, 0, 100, 100), 0, 0, 100, 100, GraphicsUnit.Pixel);
return destination.Size;
}
[Benchmark(Description = "ImageSharp Crop")]
public Size CropImageSharp()
{
using var image = new Image<Rgba32>(800, 800);
image.Mutate(x => x.Crop(100, 100));
return new Size(image.Width, image.Height);
}
}
}

20
tests/ImageSharp.Benchmarks/Samplers/DetectEdges.cs → tests/ImageSharp.Benchmarks/Processing/DetectEdges.cs

@ -1,18 +1,16 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System.IO;
using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Tests;
namespace SixLabors.ImageSharp.Benchmarks
{
using System.IO;
using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.Processing;
using CoreImage = SixLabors.ImageSharp.Image;
public class DetectEdges : BenchmarkBase
[Config(typeof(Config.MultiFramework))]
public class DetectEdges
{
private Image<Rgba32> image;
@ -21,10 +19,7 @@ namespace SixLabors.ImageSharp.Benchmarks
{
if (this.image == null)
{
using (FileStream stream = File.OpenRead("../ImageSharp.Tests/TestImages/Formats/Bmp/Car.bmp"))
{
this.image = CoreImage.Load<Rgba32>(stream);
}
this.image = Image.Load<Rgba32>(File.OpenRead(Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, TestImages.Bmp.Car)));
}
}
@ -32,6 +27,7 @@ namespace SixLabors.ImageSharp.Benchmarks
public void Cleanup()
{
this.image.Dispose();
this.image = null;
}
[Benchmark(Description = "ImageSharp DetectEdges")]

20
tests/ImageSharp.Benchmarks/Samplers/Diffuse.cs → tests/ImageSharp.Benchmarks/Processing/Diffuse.cs

@ -5,31 +5,27 @@ using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
namespace SixLabors.ImageSharp.Benchmarks.Samplers
namespace SixLabors.ImageSharp.Benchmarks.Processing
{
[Config(typeof(Config.ShortClr))]
[Config(typeof(Config.MultiFramework))]
public class Diffuse
{
[Benchmark]
public Size DoDiffuse()
{
using (var image = new Image<Rgba32>(Configuration.Default, 800, 800, Color.BlanchedAlmond))
{
image.Mutate(x => x.Dither(KnownDitherings.FloydSteinberg));
using var image = new Image<Rgba32>(Configuration.Default, 800, 800, Color.BlanchedAlmond);
image.Mutate(x => x.Dither(KnownDitherings.FloydSteinberg));
return image.Size();
}
return image.Size();
}
[Benchmark]
public Size DoDither()
{
using (var image = new Image<Rgba32>(Configuration.Default, 800, 800, Color.BlanchedAlmond))
{
image.Mutate(x => x.Dither());
using var image = new Image<Rgba32>(Configuration.Default, 800, 800, Color.BlanchedAlmond);
image.Mutate(x => x.Dither());
return image.Size();
}
return image.Size();
}
}
}

6
tests/ImageSharp.Benchmarks/Samplers/GaussianBlur.cs → tests/ImageSharp.Benchmarks/Processing/GaussianBlur.cs

@ -13,10 +13,8 @@ namespace SixLabors.ImageSharp.Benchmarks.Samplers
[Benchmark]
public void Blur()
{
using (var image = new Image<Rgba32>(Configuration.Default, 400, 400, Color.White))
{
image.Mutate(c => c.GaussianBlur());
}
using var image = new Image<Rgba32>(Configuration.Default, 400, 400, Color.White);
image.Mutate(c => c.GaussianBlur());
}
}
}

31
tests/ImageSharp.Benchmarks/Processing/HistogramEqualization.cs

@ -10,8 +10,8 @@ using SixLabors.ImageSharp.Tests;
namespace SixLabors.ImageSharp.Benchmarks.Processing
{
[Config(typeof(Config.ShortClr))]
public class HistogramEqualization : BenchmarkBase
[Config(typeof(Config.MultiFramework))]
public class HistogramEqualization
{
private Image<Rgba32> image;
@ -28,26 +28,25 @@ namespace SixLabors.ImageSharp.Benchmarks.Processing
public void Cleanup()
{
this.image.Dispose();
this.image = null;
}
[Benchmark(Description = "Global Histogram Equalization")]
public void GlobalHistogramEqualization()
{
this.image.Mutate(img => img.HistogramEqualization(new HistogramEqualizationOptions()
{
LuminanceLevels = 256,
Method = HistogramEqualizationMethod.Global
}));
}
=> this.image.Mutate(img => img.HistogramEqualization(
new HistogramEqualizationOptions()
{
LuminanceLevels = 256,
Method = HistogramEqualizationMethod.Global
}));
[Benchmark(Description = "AdaptiveHistogramEqualization (Tile interpolation)")]
public void AdaptiveHistogramEqualization()
{
this.image.Mutate(img => img.HistogramEqualization(new HistogramEqualizationOptions()
{
LuminanceLevels = 256,
Method = HistogramEqualizationMethod.AdaptiveTileInterpolation
}));
}
=> this.image.Mutate(img => img.HistogramEqualization(
new HistogramEqualizationOptions()
{
LuminanceLevels = 256,
Method = HistogramEqualizationMethod.AdaptiveTileInterpolation
}));
}
}

36
tests/ImageSharp.Benchmarks/Samplers/Resize.cs → tests/ImageSharp.Benchmarks/Processing/Resize.cs

@ -4,27 +4,23 @@
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Globalization;
using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
namespace SixLabors.ImageSharp.Benchmarks
{
[Config(typeof(Config.ShortClr))]
#pragma warning disable SA1649 // File name should match first type name
public abstract class ResizeBenchmarkBase<TPixel>
#pragma warning restore SA1649 // File name should match first type name
[Config(typeof(Config.MultiFramework))]
public abstract class Resize<TPixel>
where TPixel : unmanaged, IPixel<TPixel>
{
protected readonly Configuration Configuration = new Configuration(new JpegConfigurationModule());
private Image<TPixel> sourceImage;
private Bitmap sourceBitmap;
protected Configuration Configuration { get; } = new Configuration(new JpegConfigurationModule());
[Params("3032-400")]
public virtual string SourceToDest { get; set; }
@ -96,12 +92,10 @@ namespace SixLabors.ImageSharp.Benchmarks
protected abstract void ExecuteResizeOperation(IImageProcessingContext ctx);
}
public class Resize_Bicubic_Rgba32 : ResizeBenchmarkBase<Rgba32>
public class Resize_Bicubic_Rgba32 : Resize<Rgba32>
{
protected override void ExecuteResizeOperation(IImageProcessingContext ctx)
{
ctx.Resize(this.DestSize, this.DestSize, KnownResamplers.Bicubic);
}
=> ctx.Resize(this.DestSize, this.DestSize, KnownResamplers.Bicubic);
// RESULTS - 2019 April - ResizeWorker:
//
@ -143,12 +137,10 @@ namespace SixLabors.ImageSharp.Benchmarks
}
}
public class Resize_Bicubic_Bgra32 : ResizeBenchmarkBase<Bgra32>
public class Resize_Bicubic_Bgra32 : Resize<Bgra32>
{
protected override void ExecuteResizeOperation(IImageProcessingContext ctx)
{
ctx.Resize(this.DestSize, this.DestSize, KnownResamplers.Bicubic);
}
=> ctx.Resize(this.DestSize, this.DestSize, KnownResamplers.Bicubic);
// RESULTS (2019 April):
//
@ -171,12 +163,10 @@ namespace SixLabors.ImageSharp.Benchmarks
// 'ImageSharp, MaxDegreeOfParallelism = 1' | Core | Core | 3032 | 400 | 96.96 ms | 7.899 ms | 0.4329 ms | 0.80 | - | - | - | 44512 B |
}
public class Resize_Bicubic_Rgb24 : ResizeBenchmarkBase<Rgb24>
public class Resize_Bicubic_Rgb24 : Resize<Rgb24>
{
protected override void ExecuteResizeOperation(IImageProcessingContext ctx)
{
ctx.Resize(this.DestSize, this.DestSize, KnownResamplers.Bicubic);
}
=> ctx.Resize(this.DestSize, this.DestSize, KnownResamplers.Bicubic);
// RESULTS (2019 April):
//
@ -197,12 +187,10 @@ namespace SixLabors.ImageSharp.Benchmarks
// 'ImageSharp, MaxDegreeOfParallelism = 1' | Core | Core | 3032 | 400 | 92.47 ms | 5.683 ms | 0.3115 ms | 0.78 | 0.01 | - | - | - | 44512 B |
}
public class Resize_BicubicCompand_Rgba32 : ResizeBenchmarkBase<Rgba32>
public class Resize_BicubicCompand_Rgba32 : Resize<Rgba32>
{
protected override void ExecuteResizeOperation(IImageProcessingContext ctx)
{
ctx.Resize(this.DestSize, this.DestSize, KnownResamplers.Bicubic, true);
}
=> ctx.Resize(this.DestSize, this.DestSize, KnownResamplers.Bicubic, true);
// RESULTS (2019 April):
//

12
tests/ImageSharp.Benchmarks/Samplers/Rotate.cs → tests/ImageSharp.Benchmarks/Processing/Rotate.cs

@ -5,20 +5,18 @@ using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
namespace SixLabors.ImageSharp.Benchmarks.Samplers
namespace SixLabors.ImageSharp.Benchmarks.Processing
{
[Config(typeof(Config.ShortClr))]
[Config(typeof(Config.MultiFramework))]
public class Rotate
{
[Benchmark]
public Size DoRotate()
{
using (var image = new Image<Rgba32>(Configuration.Default, 400, 400, Color.BlanchedAlmond))
{
image.Mutate(x => x.Rotate(37.5F));
using var image = new Image<Rgba32>(Configuration.Default, 400, 400, Color.BlanchedAlmond);
image.Mutate(x => x.Rotate(37.5F));
return image.Size();
}
return image.Size();
}
}
}

12
tests/ImageSharp.Benchmarks/Samplers/Skew.cs → tests/ImageSharp.Benchmarks/Processing/Skew.cs

@ -5,20 +5,18 @@ using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
namespace SixLabors.ImageSharp.Benchmarks.Samplers
namespace SixLabors.ImageSharp.Benchmarks.Processing
{
[Config(typeof(Config.ShortClr))]
[Config(typeof(Config.MultiFramework))]
public class Skew
{
[Benchmark]
public Size DoSkew()
{
using (var image = new Image<Rgba32>(Configuration.Default, 400, 400, Color.BlanchedAlmond))
{
image.Mutate(x => x.Skew(20, 10));
using var image = new Image<Rgba32>(Configuration.Default, 400, 400, Color.BlanchedAlmond);
image.Mutate(x => x.Skew(20, 10));
return image.Size();
}
return image.Size();
}
}
}

45
tests/ImageSharp.Benchmarks/Samplers/Crop.cs

@ -1,45 +0,0 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System.Drawing;
using System.Drawing.Drawing2D;
using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using SDRectangle = System.Drawing.Rectangle;
using SDSize = System.Drawing.Size;
namespace SixLabors.ImageSharp.Benchmarks
{
[Config(typeof(Config.ShortClr))]
public class Crop : BenchmarkBase
{
[Benchmark(Baseline = true, Description = "System.Drawing Crop")]
public SDSize CropSystemDrawing()
{
using (var source = new Bitmap(800, 800))
using (var destination = new Bitmap(100, 100))
using (var graphics = Graphics.FromImage(destination))
{
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.DrawImage(source, new SDRectangle(0, 0, 100, 100), 0, 0, 100, 100, GraphicsUnit.Pixel);
return destination.Size;
}
}
[Benchmark(Description = "ImageSharp Crop")]
public Size CropResizeCore()
{
using (var image = new Image<Rgba32>(800, 800))
{
image.Mutate(x => x.Crop(100, 100));
return new Size(image.Width, image.Height);
}
}
}
}
Loading…
Cancel
Save