📷 A modern, cross-platform, 2D Graphics library for .NET
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

137 lines
5.1 KiB

// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.IO;
using System.Linq;
using System.Numerics;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.PixelFormats;
using Xunit;
using Xunit.Abstractions;
// in this file, comments are used for disabling stuff for local execution
#pragma warning disable SA1515
namespace SixLabors.ImageSharp.Tests.ProfilingBenchmarks
{
public class JpegProfilingBenchmarks : MeasureFixture
{
public JpegProfilingBenchmarks(ITestOutputHelper output)
: base(output)
{
}
public static readonly TheoryData<string, int> DecodeJpegData = new TheoryData<string, int>
{
{ TestImages.Jpeg.BenchmarkSuite.Jpeg400_SmallMonochrome, 20 },
{ TestImages.Jpeg.BenchmarkSuite.Jpeg420Exif_MidSizeYCbCr, 20 },
{ TestImages.Jpeg.BenchmarkSuite.Lake_Small444YCbCr, 40 },
// { TestImages.Jpeg.BenchmarkSuite.MissingFF00ProgressiveBedroom159_MidSize420YCbCr, 10 },
// { TestImages.Jpeg.BenchmarkSuite.BadRstProgressive518_Large444YCbCr, 5 },
{ TestImages.Jpeg.BenchmarkSuite.ExifGetString750Transform_Huge420YCbCr, 5 }
};
[Theory(Skip = ProfilingSetup.SkipProfilingTests)]
[MemberData(nameof(DecodeJpegData))]
public void DecodeJpeg(string fileName, int executionCount)
{
var decoder = new JpegDecoder()
{
IgnoreMetadata = true
};
this.DecodeJpegBenchmarkImpl(fileName, decoder, executionCount);
}
private void DecodeJpegBenchmarkImpl(string fileName, IImageDecoder decoder, int executionCount)
{
// do not run this on CI even by accident
if (TestEnvironment.RunsOnCI)
{
return;
}
if (!Vector.IsHardwareAccelerated)
{
throw new Exception("Vector.IsHardwareAccelerated == false! ('prefer32 bit' enabled?)");
}
string path = TestFile.GetInputFileFullPath(fileName);
byte[] bytes = File.ReadAllBytes(path);
this.Measure(
executionCount,
() =>
{
var img = Image.Load<Rgba32>(bytes, decoder);
img.Dispose();
},
#pragma warning disable SA1515 // Single-line comment should be preceded by blank line
// ReSharper disable once ExplicitCallerInfoArgument
$"Decode {fileName}");
#pragma warning restore SA1515 // Single-line comment should be preceded by blank line
}
[Fact(Skip = ProfilingSetup.SkipProfilingTests)]
public void EncodeJpeg_SingleMidSize()
{
string path = TestFile.GetInputFileFullPath(TestImages.Jpeg.BenchmarkSuite.Jpeg420Exif_MidSizeYCbCr);
using var image = Image.Load(path);
image.Metadata.ExifProfile = null;
using var ms = new MemoryStream();
for (int i = 0; i < 30; i++)
{
image.SaveAsJpeg(ms);
ms.Seek(0, SeekOrigin.Begin);
}
}
// Benchmark, enable manually!
[Theory(Skip = ProfilingSetup.SkipProfilingTests)]
[InlineData(1, 75, JpegColorType.YCbCrRatio420)]
[InlineData(30, 75, JpegColorType.YCbCrRatio420)]
[InlineData(30, 75, JpegColorType.YCbCrRatio444)]
[InlineData(30, 100, JpegColorType.YCbCrRatio444)]
public void EncodeJpeg(int executionCount, int quality, JpegColorType colorType)
{
// do not run this on CI even by accident
if (TestEnvironment.RunsOnCI)
{
return;
}
string[] testFiles = TestImages.Bmp.Benchmark
.Concat(new[] { TestImages.Jpeg.Baseline.Calliphora, TestImages.Jpeg.Baseline.Cmyk }).ToArray();
Image<Rgba32>[] testImages = testFiles.Select(
tf => TestImageProvider<Rgba32>.File(tf, pixelTypeOverride: PixelTypes.Rgba32).GetImage()).ToArray();
using (var ms = new MemoryStream())
{
this.Measure(
executionCount,
() =>
{
foreach (Image<Rgba32> img in testImages)
{
var options = new JpegEncoder { Quality = quality, ColorType = colorType };
img.Save(ms, options);
ms.Seek(0, SeekOrigin.Begin);
}
},
#pragma warning disable SA1515 // Single-line comment should be preceded by blank line
// ReSharper disable once ExplicitCallerInfoArgument
$@"Encode {testFiles.Length} images");
#pragma warning restore SA1515 // Single-line comment should be preceded by blank line
}
foreach (Image<Rgba32> image in testImages)
{
image.Dispose();
}
}
}
}