mirror of https://github.com/SixLabors/ImageSharp
committed by
GitHub
26 changed files with 575 additions and 264 deletions
@ -1,161 +0,0 @@ |
|||
// 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.Formats.Jpeg; |
|||
using SixLabors.ImageSharp.PixelFormats; |
|||
using SixLabors.ImageSharp.Tests; |
|||
using SDImage = System.Drawing.Image; |
|||
|
|||
namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg |
|||
{ |
|||
public class EncodeJpeg |
|||
{ |
|||
[Params(75, 90, 100)] |
|||
public int Quality; |
|||
|
|||
private const string TestImage = TestImages.Jpeg.BenchmarkSuite.Jpeg420Exif_MidSizeYCbCr; |
|||
|
|||
// System.Drawing
|
|||
private SDImage bmpDrawing; |
|||
private Stream bmpStream; |
|||
private ImageCodecInfo jpegCodec; |
|||
private EncoderParameters encoderParameters; |
|||
|
|||
// ImageSharp
|
|||
private Image<Rgba32> bmpCore; |
|||
private Image<L8> bmpLuminance; |
|||
private JpegEncoder encoder400; |
|||
private JpegEncoder encoder420; |
|||
private JpegEncoder encoder444; |
|||
private JpegEncoder encoderRgb; |
|||
|
|||
private MemoryStream destinationStream; |
|||
|
|||
[GlobalSetup] |
|||
public void ReadImages() |
|||
{ |
|||
if (this.bmpStream == null) |
|||
{ |
|||
this.bmpStream = File.OpenRead(Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, TestImage)); |
|||
|
|||
this.bmpCore = Image.Load<Rgba32>(this.bmpStream); |
|||
this.bmpCore.Metadata.ExifProfile = null; |
|||
this.bmpLuminance = this.bmpCore.CloneAs<L8>(); |
|||
this.encoder400 = new JpegEncoder { Quality = this.Quality, ColorType = JpegColorType.Luminance }; |
|||
this.encoder420 = new JpegEncoder { Quality = this.Quality, ColorType = JpegColorType.YCbCrRatio420 }; |
|||
this.encoder444 = new JpegEncoder { Quality = this.Quality, ColorType = JpegColorType.YCbCrRatio444 }; |
|||
this.encoderRgb = new JpegEncoder { Quality = this.Quality, ColorType = JpegColorType.Rgb }; |
|||
|
|||
this.bmpStream.Position = 0; |
|||
this.bmpDrawing = SDImage.FromStream(this.bmpStream); |
|||
this.jpegCodec = GetEncoder(ImageFormat.Jpeg); |
|||
this.encoderParameters = new EncoderParameters(1); |
|||
|
|||
// Quality cast to long is necessary
|
|||
#pragma warning disable IDE0004 // Remove Unnecessary Cast
|
|||
this.encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, (long)this.Quality); |
|||
#pragma warning restore IDE0004 // Remove Unnecessary Cast
|
|||
|
|||
this.destinationStream = new MemoryStream(); |
|||
} |
|||
} |
|||
|
|||
[GlobalCleanup] |
|||
public void Cleanup() |
|||
{ |
|||
this.bmpStream.Dispose(); |
|||
this.bmpStream = null; |
|||
|
|||
this.destinationStream.Dispose(); |
|||
this.destinationStream = null; |
|||
|
|||
this.bmpCore.Dispose(); |
|||
this.bmpDrawing.Dispose(); |
|||
|
|||
this.encoderParameters.Dispose(); |
|||
} |
|||
|
|||
[Benchmark(Baseline = true, Description = "System.Drawing Jpeg 4:2:0")] |
|||
public void JpegSystemDrawing() |
|||
{ |
|||
this.bmpDrawing.Save(this.destinationStream, this.jpegCodec, this.encoderParameters); |
|||
this.destinationStream.Seek(0, SeekOrigin.Begin); |
|||
} |
|||
|
|||
[Benchmark(Description = "ImageSharp (greyscale) Jpeg 4:0:0")] |
|||
public void JpegCore400() |
|||
{ |
|||
this.bmpLuminance.SaveAsJpeg(this.destinationStream, this.encoder400); |
|||
this.destinationStream.Seek(0, SeekOrigin.Begin); |
|||
} |
|||
|
|||
|
|||
[Benchmark(Description = "ImageSharp Jpeg 4:2:0")] |
|||
public void JpegCore420() |
|||
{ |
|||
this.bmpCore.SaveAsJpeg(this.destinationStream, this.encoder420); |
|||
this.destinationStream.Seek(0, SeekOrigin.Begin); |
|||
} |
|||
|
|||
[Benchmark(Description = "ImageSharp Jpeg 4:4:4")] |
|||
public void JpegCore444() |
|||
{ |
|||
this.bmpCore.SaveAsJpeg(this.destinationStream, this.encoder444); |
|||
this.destinationStream.Seek(0, SeekOrigin.Begin); |
|||
} |
|||
|
|||
[Benchmark(Description = "ImageSharp Jpeg rgb")] |
|||
public void JpegRgb() |
|||
{ |
|||
this.bmpCore.SaveAsJpeg(this.destinationStream, this.encoderRgb); |
|||
this.destinationStream.Seek(0, SeekOrigin.Begin); |
|||
} |
|||
|
|||
// https://docs.microsoft.com/en-us/dotnet/api/system.drawing.imaging.encoderparameter?redirectedfrom=MSDN&view=net-5.0
|
|||
private static ImageCodecInfo GetEncoder(ImageFormat format) |
|||
{ |
|||
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders(); |
|||
foreach (ImageCodecInfo codec in codecs) |
|||
{ |
|||
if (codec.FormatID == format.Guid) |
|||
{ |
|||
return codec; |
|||
} |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
} |
|||
} |
|||
|
|||
/* |
|||
BenchmarkDotNet=v0.13.0, OS=linuxmint 20.3 |
|||
AMD Ryzen 7 5800X, 1 CPU, 16 logical and 8 physical cores |
|||
.NET SDK=6.0.200 |
|||
[Host] : .NET Core 3.1.22 (CoreCLR 4.700.21.56803, CoreFX 4.700.21.57101), X64 RyuJIT |
|||
DefaultJob : .NET Core 3.1.22 (CoreCLR 4.700.21.56803, CoreFX 4.700.21.57101), X64 RyuJIT |
|||
|
|||
|
|||
| Method | Quality | Mean | Error | StdDev | Ratio | RatioSD | |
|||
|------------------------------------ |-------- |----------:|----------:|----------:|------:|--------:| |
|||
| 'System.Drawing Jpeg 4:2:0' | 75 | 9.157 ms | 0.0138 ms | 0.0123 ms | 1.00 | 0.00 | |
|||
| 'ImageSharp (greyscale) Jpeg 4:0:0' | 75 | 12.142 ms | 0.1321 ms | 0.1236 ms | 1.33 | 0.01 | |
|||
| 'ImageSharp Jpeg 4:2:0' | 75 | 19.655 ms | 0.1057 ms | 0.0883 ms | 2.15 | 0.01 | |
|||
| 'ImageSharp Jpeg 4:4:4' | 75 | 19.157 ms | 0.2852 ms | 0.2668 ms | 2.09 | 0.03 | |
|||
| 'ImageSharp Jpeg rgb' | 75 | 26.404 ms | 0.3803 ms | 0.3557 ms | 2.89 | 0.04 | |
|||
| | | | | | | | |
|||
| 'System.Drawing Jpeg 4:2:0' | 90 | 10.828 ms | 0.0727 ms | 0.0680 ms | 1.00 | 0.00 | |
|||
| 'ImageSharp (greyscale) Jpeg 4:0:0' | 90 | 14.918 ms | 0.1089 ms | 0.1019 ms | 1.38 | 0.01 | |
|||
| 'ImageSharp Jpeg 4:2:0' | 90 | 23.718 ms | 0.0301 ms | 0.0267 ms | 2.19 | 0.02 | |
|||
| 'ImageSharp Jpeg 4:4:4' | 90 | 23.857 ms | 0.2387 ms | 0.2233 ms | 2.20 | 0.03 | |
|||
| 'ImageSharp Jpeg rgb' | 90 | 34.700 ms | 0.2207 ms | 0.2064 ms | 3.20 | 0.03 | |
|||
| | | | | | | | |
|||
| 'System.Drawing Jpeg 4:2:0' | 100 | 13.478 ms | 0.0054 ms | 0.0048 ms | 1.00 | 0.00 | |
|||
| 'ImageSharp (greyscale) Jpeg 4:0:0' | 100 | 19.446 ms | 0.0803 ms | 0.0751 ms | 1.44 | 0.01 | |
|||
| 'ImageSharp Jpeg 4:2:0' | 100 | 30.339 ms | 0.4578 ms | 0.4282 ms | 2.25 | 0.03 | |
|||
| 'ImageSharp Jpeg 4:4:4' | 100 | 39.056 ms | 0.1779 ms | 0.1664 ms | 2.90 | 0.01 | |
|||
| 'ImageSharp Jpeg rgb' | 100 | 51.828 ms | 0.3336 ms | 0.3121 ms | 3.85 | 0.02 | |
|||
*/ |
|||
@ -0,0 +1,112 @@ |
|||
// 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.Formats.Jpeg; |
|||
using SixLabors.ImageSharp.PixelFormats; |
|||
using SixLabors.ImageSharp.Tests; |
|||
using SkiaSharp; |
|||
using SDImage = System.Drawing.Image; |
|||
|
|||
namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg |
|||
{ |
|||
/// <summary>
|
|||
/// Benchmark for performance comparison between other codecs.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// This benchmarks tests baseline 4:2:0 chroma sampling path.
|
|||
/// </remarks>
|
|||
public class EncodeJpegComparison |
|||
{ |
|||
// Big enough, 4:4:4 chroma sampling
|
|||
private const string TestImage = TestImages.Jpeg.Baseline.Calliphora; |
|||
|
|||
// Change/add parameters for extra benchmarks
|
|||
[Params(75, 90, 100)] |
|||
public int Quality; |
|||
|
|||
private MemoryStream destinationStream; |
|||
|
|||
// ImageSharp
|
|||
private Image<Rgba32> imageImageSharp; |
|||
private JpegEncoder encoderImageSharp; |
|||
|
|||
// SkiaSharp
|
|||
private SKBitmap imageSkiaSharp; |
|||
|
|||
[GlobalSetup(Target = nameof(BenchmarkImageSharp))] |
|||
public void SetupImageSharp() |
|||
{ |
|||
using FileStream imageBinaryStream = File.OpenRead(Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, TestImage)); |
|||
|
|||
this.imageImageSharp = Image.Load<Rgba32>(imageBinaryStream); |
|||
this.encoderImageSharp = new JpegEncoder { Quality = this.Quality, ColorType = JpegColorType.YCbCrRatio420 }; |
|||
|
|||
this.destinationStream = new MemoryStream(); |
|||
} |
|||
|
|||
[GlobalCleanup(Target = nameof(BenchmarkImageSharp))] |
|||
public void CleanupImageSharp() |
|||
{ |
|||
this.imageImageSharp.Dispose(); |
|||
this.imageImageSharp = null; |
|||
|
|||
this.destinationStream.Dispose(); |
|||
this.destinationStream = null; |
|||
} |
|||
|
|||
[Benchmark(Description = "ImageSharp")] |
|||
public void BenchmarkImageSharp() |
|||
{ |
|||
this.imageImageSharp.SaveAsJpeg(this.destinationStream, this.encoderImageSharp); |
|||
this.destinationStream.Seek(0, SeekOrigin.Begin); |
|||
} |
|||
|
|||
[GlobalSetup(Target = nameof(BenchmarkSkiaSharp))] |
|||
public void SetupSkiaSharp() |
|||
{ |
|||
using FileStream imageBinaryStream = File.OpenRead(Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, TestImage)); |
|||
|
|||
this.imageSkiaSharp = SKBitmap.Decode(imageBinaryStream); |
|||
|
|||
this.destinationStream = new MemoryStream(); |
|||
} |
|||
|
|||
[GlobalCleanup(Target = nameof(BenchmarkSkiaSharp))] |
|||
public void CleanupSkiaSharp() |
|||
{ |
|||
this.imageSkiaSharp.Dispose(); |
|||
this.imageSkiaSharp = null; |
|||
|
|||
this.destinationStream.Dispose(); |
|||
this.destinationStream = null; |
|||
} |
|||
|
|||
[Benchmark(Description = "SkiaSharp")] |
|||
public void BenchmarkSkiaSharp() |
|||
{ |
|||
this.imageSkiaSharp.Encode(SKEncodedImageFormat.Jpeg, this.Quality).SaveTo(this.destinationStream); |
|||
this.destinationStream.Seek(0, SeekOrigin.Begin); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/* |
|||
BenchmarkDotNet=v0.13.0, OS=Windows 10.0.19044 |
|||
Intel Core i7-6700K CPU 4.00GHz (Skylake), 1 CPU, 8 logical and 4 physical cores |
|||
.NET SDK=6.0.100-preview.3.21202.5 |
|||
[Host] : .NET Core 3.1.21 (CoreCLR 4.700.21.51404, CoreFX 4.700.21.51508), X64 RyuJIT |
|||
DefaultJob : .NET Core 3.1.21 (CoreCLR 4.700.21.51404, CoreFX 4.700.21.51508), X64 RyuJIT |
|||
|
|||
|
|||
| Method | Quality | Mean | Error | StdDev | |
|||
|----------- |-------- |----------:|----------:|----------:| |
|||
| ImageSharp | 75 | 6.820 ms | 0.0374 ms | 0.0312 ms | |
|||
| SkiaSharp | 75 | 16.417 ms | 0.3238 ms | 0.4747 ms | |
|||
| ImageSharp | 90 | 7.849 ms | 0.1565 ms | 0.3126 ms | |
|||
| SkiaSharp | 90 | 16.893 ms | 0.2200 ms | 0.2058 ms | |
|||
| ImageSharp | 100 | 11.016 ms | 0.2087 ms | 0.1850 ms | |
|||
| SkiaSharp | 100 | 20.410 ms | 0.2583 ms | 0.2290 ms | |
|||
*/ |
|||
@ -0,0 +1,89 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System.Collections.Generic; |
|||
using System.IO; |
|||
using BenchmarkDotNet.Attributes; |
|||
using SixLabors.ImageSharp.Formats.Jpeg; |
|||
using SixLabors.ImageSharp.PixelFormats; |
|||
using SixLabors.ImageSharp.Tests; |
|||
|
|||
namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg |
|||
{ |
|||
/// <summary>
|
|||
/// Benchmark for all available encoding features of the Jpeg file type.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// This benchmark does NOT compare ImageSharp to any other jpeg codecs.
|
|||
/// </remarks>
|
|||
public class EncodeJpegFeatures |
|||
{ |
|||
// Big enough, 4:4:4 chroma sampling
|
|||
// No metadata
|
|||
private const string TestImage = TestImages.Jpeg.Baseline.Calliphora; |
|||
|
|||
public static IEnumerable<JpegColorType> ColorSpaceValues => |
|||
new[] { JpegColorType.Luminance, JpegColorType.Rgb, JpegColorType.YCbCrRatio420, JpegColorType.YCbCrRatio444 }; |
|||
|
|||
[Params(75, 90, 100)] |
|||
public int Quality; |
|||
|
|||
[ParamsSource(nameof(ColorSpaceValues), Priority = -100)] |
|||
public JpegColorType TargetColorSpace; |
|||
|
|||
private Image<Rgb24> bmpCore; |
|||
private JpegEncoder encoder; |
|||
|
|||
private MemoryStream destinationStream; |
|||
|
|||
[GlobalSetup] |
|||
public void Setup() |
|||
{ |
|||
using FileStream imageBinaryStream = File.OpenRead(Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, TestImage)); |
|||
this.bmpCore = Image.Load<Rgb24>(imageBinaryStream); |
|||
this.encoder = new JpegEncoder { Quality = this.Quality, ColorType = this.TargetColorSpace }; |
|||
this.destinationStream = new MemoryStream(); |
|||
} |
|||
|
|||
[GlobalCleanup] |
|||
public void Cleanup() |
|||
{ |
|||
this.bmpCore.Dispose(); |
|||
this.bmpCore = null; |
|||
|
|||
this.destinationStream.Dispose(); |
|||
this.destinationStream = null; |
|||
} |
|||
|
|||
[Benchmark] |
|||
public void Benchmark() |
|||
{ |
|||
this.bmpCore.SaveAsJpeg(this.destinationStream, this.encoder); |
|||
this.destinationStream.Seek(0, SeekOrigin.Begin); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/* |
|||
BenchmarkDotNet=v0.13.0, OS=Windows 10.0.19044 |
|||
Intel Core i7-6700K CPU 4.00GHz (Skylake), 1 CPU, 8 logical and 4 physical cores |
|||
.NET SDK=6.0.100-preview.3.21202.5 |
|||
[Host] : .NET Core 3.1.21 (CoreCLR 4.700.21.51404, CoreFX 4.700.21.51508), X64 RyuJIT |
|||
DefaultJob : .NET Core 3.1.21 (CoreCLR 4.700.21.51404, CoreFX 4.700.21.51508), X64 RyuJIT |
|||
|
|||
|
|||
| Method | TargetColorSpace | Quality | Mean | Error | StdDev | |
|||
|---------- |----------------- |-------- |----------:|----------:|----------:| |
|||
| Benchmark | Luminance | 75 | 7.055 ms | 0.1411 ms | 0.3297 ms | |
|||
| Benchmark | Rgb | 75 | 12.139 ms | 0.0645 ms | 0.0538 ms | |
|||
| Benchmark | YCbCrRatio420 | 75 | 6.463 ms | 0.0282 ms | 0.0235 ms | |
|||
| Benchmark | YCbCrRatio444 | 75 | 8.616 ms | 0.0422 ms | 0.0374 ms | |
|||
| Benchmark | Luminance | 90 | 7.011 ms | 0.0361 ms | 0.0301 ms | |
|||
| Benchmark | Rgb | 90 | 13.119 ms | 0.0947 ms | 0.0886 ms | |
|||
| Benchmark | YCbCrRatio420 | 90 | 6.786 ms | 0.0328 ms | 0.0274 ms | |
|||
| Benchmark | YCbCrRatio444 | 90 | 8.672 ms | 0.0772 ms | 0.0722 ms | |
|||
| Benchmark | Luminance | 100 | 9.554 ms | 0.1211 ms | 0.1012 ms | |
|||
| Benchmark | Rgb | 100 | 19.475 ms | 0.1080 ms | 0.0958 ms | |
|||
| Benchmark | YCbCrRatio420 | 100 | 10.146 ms | 0.0585 ms | 0.0519 ms | |
|||
| Benchmark | YCbCrRatio444 | 100 | 15.317 ms | 0.0709 ms | 0.0592 ms | |
|||
*/ |
|||
@ -1,34 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System.Collections.Generic; |
|||
using System.Drawing.Imaging; |
|||
using BenchmarkDotNet.Attributes; |
|||
using SixLabors.ImageSharp.Formats.Jpeg; |
|||
|
|||
namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg |
|||
{ |
|||
[Config(typeof(Config.ShortMultiFramework))] |
|||
public class EncodeJpegMultiple : MultiImageBenchmarkBase.WithImagesPreloaded |
|||
{ |
|||
protected override IEnumerable<string> InputImageSubfoldersOrFiles => new[] { "Bmp/", "Jpg/baseline" }; |
|||
|
|||
protected override IEnumerable<string> SearchPatterns => new[] { "*.bmp", "*.jpg" }; |
|||
|
|||
[Benchmark(Description = "EncodeJpegMultiple - ImageSharp")] |
|||
public void EncodeJpegImageSharp() |
|||
=> 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) => |
|||
{ |
|||
img.Save(ms, ImageFormat.Jpeg); |
|||
return null; |
|||
}); |
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:7048dee15946bf981e5b0d2481ffcb8a64684fddca07172275b13a05f01b6b63 |
|||
size 1631109 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:4c52500be37a8ea1ee1caeb78c79e44b02e10912df4f6db65313c6745573c8ee |
|||
size 250451 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:874ef7a59491ba68364312b7bc27b6620d15ce8b1d5b780f57c6e6d8b919ef1f |
|||
size 73922 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:d4faa8617d10ea5f79225c528c0a6d5c36f73d315e46150703df5ca5008ea1bd |
|||
size 73922 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:6a17791068b9c3eb40db3157a9103892aaf4a5a74072c93006bfa702ba5545e5 |
|||
size 80428 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:63fef29d79f8d707c74b6e083de6bb2ad41dde1d9b1aea5bd7729a2f7399132e |
|||
size 80344 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:9d91f0740d6df983b5e5fe904c22fe86c2a7ffd86673fb078092d80c96359fc1 |
|||
size 53666 |
|||
Loading…
Reference in new issue