// // Copyright (c) James Jackson-South and contributors. // Licensed under the Apache License, Version 2.0. // namespace ImageSharp.Benchmarks { using System; using BenchmarkDotNet.Attributes; using ImageSharp.PixelFormats; using CoreSize = ImageSharp.Size; using System.Numerics; using ImageSharp.Memory; using ImageSharp.PixelFormats.PixelBlenders; public class PorterDuffBulkVsPixel : BenchmarkBase { private void BulkVectorConvert(Span destination, Span background, Span source, Span amount) where TPixel : struct, IPixel { Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); using (Buffer buffer = new Buffer(destination.Length * 3)) { Span destinationSpan = buffer.Slice(0, destination.Length); Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); PixelOperations.Instance.ToVector4(background, backgroundSpan, destination.Length); PixelOperations.Instance.ToVector4(source, sourceSpan, destination.Length); for (int i = 0; i < destination.Length; i++) { destinationSpan[i] = PorterDuffFunctions.NormalBlendFunction(backgroundSpan[i], sourceSpan[i], amount[i]); } PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); } } private void BulkPixelConvert(Span destination, Span background, Span source, Span amount) where TPixel : struct, IPixel { Guard.MustBeGreaterThanOrEqualTo(destination.Length, background.Length, nameof(destination)); Guard.MustBeGreaterThanOrEqualTo(source.Length, background.Length, nameof(destination)); Guard.MustBeGreaterThanOrEqualTo(amount.Length, background.Length, nameof(destination)); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.NormalBlendFunction(destination[i], source[i], amount[i]); } } [Benchmark(Description = "ImageSharp BulkVectorConvert")] public CoreSize BulkVectorConvert() { using (Image image = new Image(800, 800)) { Buffer amounts = new Buffer(image.Width); for (int x = 0; x < image.Width; x++) { amounts[x] = 1; } using (PixelAccessor pixels = image.Lock()) { for (int y = 0; y < image.Height; y++) { Span span = pixels.GetRowSpan(y); BulkVectorConvert(span, span, span, amounts); } } return new CoreSize(image.Width, image.Height); } } [Benchmark(Description = "ImageSharp BulkPixelConvert")] public CoreSize BulkPixelConvert() { using (Image image = new Image(800, 800)) { Buffer amounts = new Buffer(image.Width); for (int x = 0; x < image.Width; x++) { amounts[x] = 1; } using (PixelAccessor pixels = image.Lock()) { for (int y = 0; y < image.Height; y++) { Span span = pixels.GetRowSpan(y); BulkPixelConvert(span, span, span, amounts); } } return new CoreSize(image.Width, image.Height); } } } }