From 4a791cc516a5166ad6e8e32267daa3974327d9f4 Mon Sep 17 00:00:00 2001 From: Vicente Penades Date: Mon, 27 Aug 2018 23:05:38 +0200 Subject: [PATCH] Refactored PixelBlenders so it generates much less code and allows for two loop variations. Generalised DrawingImage methods to support drawing images with a format different than the destination image at no cost. --- .../Processing/DrawImageExtensions.cs | 96 +- .../Processors/Drawing/DrawImageProcessor.cs | 53 +- .../DefaultPixelBlenders.Generated.cs | 3476 +++++++---------- .../DefaultPixelBlenders.Generated.tt | 39 +- .../PixelFormats/PixelBlender{TPixel}.cs | 136 +- 5 files changed, 1641 insertions(+), 2159 deletions(-) diff --git a/src/ImageSharp.Drawing/Processing/DrawImageExtensions.cs b/src/ImageSharp.Drawing/Processing/DrawImageExtensions.cs index 8ccbe22acb..d236ec35c6 100644 --- a/src/ImageSharp.Drawing/Processing/DrawImageExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/DrawImageExtensions.cs @@ -15,107 +15,123 @@ namespace SixLabors.ImageSharp.Processing /// /// Draws the given image together with the current one by blending their pixels. /// - /// The pixel format. + /// The pixel format of the destination image. + /// The pixel format of the source image. /// The image this method extends. /// The image to blend with the currently processing image. /// The opacity of the image to blend. Must be between 0 and 1. - /// The . - public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, float opacity) - where TPixel : struct, IPixel - => source.ApplyProcessor(new DrawImageProcessor(image, Point.Empty, GraphicsOptions.Default.ColorBlendingMode, GraphicsOptions.Default.AlphaCompositionMode, opacity)); + /// The . + public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, float opacity) + where TPixelDst : struct, IPixel + where TPixelSrc : struct, IPixel + => source.ApplyProcessor(new DrawImageProcessor(image, Point.Empty, GraphicsOptions.Default.ColorBlendingMode, GraphicsOptions.Default.AlphaCompositionMode, opacity)); /// /// Draws the given image together with the current one by blending their pixels. /// - /// The pixel format. + /// The pixel format of the destination image. + /// The pixel format of the source image. /// The image this method extends. /// The image to blend with the currently processing image. /// The blending mode. /// The opacity of the image to blend. Must be between 0 and 1. - /// The . - public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, PixelColorBlendingMode colorBlending, float opacity) - where TPixel : struct, IPixel - => source.ApplyProcessor(new DrawImageProcessor(image, Point.Empty, colorBlending, GraphicsOptions.Default.AlphaCompositionMode, opacity)); + /// The . + public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, PixelColorBlendingMode colorBlending, float opacity) + where TPixelDst : struct, IPixel + where TPixelSrc : struct, IPixel + => source.ApplyProcessor(new DrawImageProcessor(image, Point.Empty, colorBlending, GraphicsOptions.Default.AlphaCompositionMode, opacity)); /// /// Draws the given image together with the current one by blending their pixels. /// - /// The pixel format. + /// The pixel format of the destination image. + /// The pixel format of the source image. /// The image this method extends. /// The image to blend with the currently processing image. /// The color blending mode. /// The alpha composition mode. /// The opacity of the image to blend. Must be between 0 and 1. - /// The . - public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, PixelColorBlendingMode colorBlending, PixelAlphaCompositionMode alphaComposition, float opacity) - where TPixel : struct, IPixel - => source.ApplyProcessor(new DrawImageProcessor(image, Point.Empty, colorBlending, alphaComposition, opacity)); + /// The . + public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, PixelColorBlendingMode colorBlending, PixelAlphaCompositionMode alphaComposition, float opacity) + where TPixelDst : struct, IPixel + where TPixelSrc : struct, IPixel + => source.ApplyProcessor(new DrawImageProcessor(image, Point.Empty, colorBlending, alphaComposition, opacity)); /// /// Draws the given image together with the current one by blending their pixels. /// - /// The pixel format. + /// The pixel format of the destination image. + /// The pixel format of the source image. /// The image this method extends. /// The image to blend with the currently processing image. /// The options, including the blending type and blending amount. - /// The . - public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, GraphicsOptions options) - where TPixel : struct, IPixel - => source.ApplyProcessor(new DrawImageProcessor(image, Point.Empty, options.ColorBlendingMode, options.AlphaCompositionMode, options.BlendPercentage)); + /// The . + public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, GraphicsOptions options) + where TPixelDst : struct, IPixel + where TPixelSrc : struct, IPixel + => source.ApplyProcessor(new DrawImageProcessor(image, Point.Empty, options.ColorBlendingMode, options.AlphaCompositionMode, options.BlendPercentage)); /// /// Draws the given image together with the current one by blending their pixels. /// - /// The pixel format. + /// The pixel format of the destination image. + /// The pixel format of the source image. /// The image this method extends. /// The image to blend with the currently processing image. /// The location to draw the blended image. /// The opacity of the image to blend. Must be between 0 and 1. - /// The . - public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, Point location, float opacity) - where TPixel : struct, IPixel - => source.ApplyProcessor(new DrawImageProcessor(image, location, GraphicsOptions.Default.ColorBlendingMode, GraphicsOptions.Default.AlphaCompositionMode, opacity)); + /// The . + public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, Point location, float opacity) + where TPixelDst : struct, IPixel + where TPixelSrc : struct, IPixel + => source.ApplyProcessor(new DrawImageProcessor(image, location, GraphicsOptions.Default.ColorBlendingMode, GraphicsOptions.Default.AlphaCompositionMode, opacity)); /// /// Draws the given image together with the current one by blending their pixels. /// - /// The pixel format. + /// The pixel format of the destination image. + /// The pixel format of the source image. /// The image this method extends. /// The image to blend with the currently processing image. /// The location to draw the blended image. /// The color blending to apply. /// The opacity of the image to blend. Must be between 0 and 1. - /// The . - public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, Point location, PixelColorBlendingMode colorBlending, float opacity) - where TPixel : struct, IPixel - => source.ApplyProcessor(new DrawImageProcessor(image, location, colorBlending, GraphicsOptions.Default.AlphaCompositionMode, opacity)); + /// The . + public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, Point location, PixelColorBlendingMode colorBlending, float opacity) + where TPixelDst : struct, IPixel + where TPixelSrc : struct, IPixel + => source.ApplyProcessor(new DrawImageProcessor(image, location, colorBlending, GraphicsOptions.Default.AlphaCompositionMode, opacity)); /// /// Draws the given image together with the current one by blending their pixels. /// - /// The pixel format. + /// The pixel format of the destination image. + /// The pixel format of the source image. /// The image this method extends. /// The image to blend with the currently processing image. /// The location to draw the blended image. /// The color blending to apply. /// The alpha composition mode. /// The opacity of the image to blend. Must be between 0 and 1. - /// The . - public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, Point location, PixelColorBlendingMode colorBlending, PixelAlphaCompositionMode alphaComposition, float opacity) - where TPixel : struct, IPixel - => source.ApplyProcessor(new DrawImageProcessor(image, location, colorBlending, alphaComposition, opacity)); + /// The . + public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, Point location, PixelColorBlendingMode colorBlending, PixelAlphaCompositionMode alphaComposition, float opacity) + where TPixelDst : struct, IPixel + where TPixelSrc : struct, IPixel + => source.ApplyProcessor(new DrawImageProcessor(image, location, colorBlending, alphaComposition, opacity)); /// /// Draws the given image together with the current one by blending their pixels. /// - /// The pixel format. + /// The pixel format of the destination image. + /// The pixel format of the source image. /// The image this method extends. /// The image to blend with the currently processing image. /// The location to draw the blended image. /// The options containing the blend mode and opacity. - /// The . - public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, Point location, GraphicsOptions options) - where TPixel : struct, IPixel - => source.ApplyProcessor(new DrawImageProcessor(image, location, options.ColorBlendingMode, options.AlphaCompositionMode, options.BlendPercentage)); + /// The . + public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, Point location, GraphicsOptions options) + where TPixelDst : struct, IPixel + where TPixelSrc : struct, IPixel + => source.ApplyProcessor(new DrawImageProcessor(image, location, options.ColorBlendingMode, options.AlphaCompositionMode, options.BlendPercentage)); } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs index 324d25e097..4e6018e07a 100644 --- a/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs +++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs @@ -15,32 +15,34 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing /// /// Combines two images together by blending the pixels. /// - /// The pixel format. - internal class DrawImageProcessor : ImageProcessor - where TPixel : struct, IPixel + /// The pixel format of destination image. + /// The pixel format os source image. + internal class DrawImageProcessor : ImageProcessor + where TPixelDst : struct, IPixel + where TPixelSrc : struct, IPixel { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The image to blend with the currently processing image. /// The location to draw the blended image. /// The blending mode to use when drawing the image. /// The Alpha blending mode to use when drawing the image. /// The opacity of the image to blend. Must be between 0 and 1. - public DrawImageProcessor(Image image, Point location, PixelColorBlendingMode colorBlendingMode, PixelAlphaCompositionMode alphaCompositionMode, float opacity) + public DrawImageProcessor(Image image, Point location, PixelColorBlendingMode colorBlendingMode, PixelAlphaCompositionMode alphaCompositionMode, float opacity) { Guard.MustBeBetweenOrEqualTo(opacity, 0, 1, nameof(opacity)); this.Image = image; this.Opacity = opacity; - this.Blender = PixelOperations.Instance.GetPixelBlender(colorBlendingMode, alphaCompositionMode); + this.Blender = PixelOperations.Instance.GetPixelBlender(colorBlendingMode, alphaCompositionMode); this.Location = location; } /// /// Gets the image to blend /// - public Image Image { get; } + public Image Image { get; } /// /// Gets the opacity of the image to blend @@ -50,7 +52,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing /// /// Gets the pixel blender /// - public PixelBlender Blender { get; } + public PixelBlender Blender { get; } /// /// Gets the location to draw the blended image @@ -58,10 +60,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing public Point Location { get; } /// - protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) { - Image targetImage = this.Image; - PixelBlender blender = this.Blender; + Image targetImage = this.Image; + PixelBlender blender = this.Blender; int locationY = this.Location.Y; // Align start/end positions. @@ -76,23 +78,18 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing int width = maxX - minX; - MemoryAllocator memoryAllocator = this.Image.GetConfiguration().MemoryAllocator; - - using (IMemoryOwner amount = memoryAllocator.Allocate(width)) - { - amount.GetSpan().Fill(this.Opacity); - - ParallelFor.WithConfiguration( - minY, - maxY, - configuration, - y => - { - Span background = source.GetPixelRowSpan(y).Slice(minX, width); - Span foreground = targetImage.GetPixelRowSpan(y - locationY).Slice(targetX, width); - blender.Blend(memoryAllocator, background, background, foreground, amount.GetSpan()); - }); - } + MemoryAllocator memoryAllocator = this.Image.GetConfiguration().MemoryAllocator; + + ParallelFor.WithConfiguration( + minY, + maxY, + configuration, + y => + { + Span background = source.GetPixelRowSpan(y).Slice(minX, width); + Span foreground = targetImage.GetPixelRowSpan(y - locationY).Slice(targetX, width); + blender.Blend(memoryAllocator, background, background, foreground, this.Opacity); + }); } } } \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.cs b/src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.cs index 9b1e29db81..cc6743d567 100644 --- a/src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.cs @@ -1,12 +1,19 @@ -// Copyright (c) Six Labors and contributors. + + + + + + + +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. // -using System; -using System.Numerics; -using System.Buffers; - -using SixLabors.ImageSharp.Memory; +using System; +using System.Numerics; +using System.Buffers; + +using SixLabors.ImageSharp.Memory; using SixLabors.Memory; namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders @@ -26,6 +33,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders where TPixel : struct, IPixel { + internal class NormalSrc : PixelBlender { /// @@ -40,31 +48,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.NormalSrc(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.NormalSrc(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.NormalSrc(background[i], source[i], amount[i]); + } } } + internal class MultiplySrc : PixelBlender { /// @@ -79,31 +81,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.MultiplySrc(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.MultiplySrc(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.MultiplySrc(background[i], source[i], amount[i]); + } } } + internal class AddSrc : PixelBlender { /// @@ -118,31 +114,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.AddSrc(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.AddSrc(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.AddSrc(background[i], source[i], amount[i]); + } } } + internal class SubtractSrc : PixelBlender { /// @@ -157,31 +147,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.SubtractSrc(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.SubtractSrc(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.SubtractSrc(background[i], source[i], amount[i]); + } } } + internal class ScreenSrc : PixelBlender { /// @@ -196,31 +180,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.ScreenSrc(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.ScreenSrc(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.ScreenSrc(background[i], source[i], amount[i]); + } } } + internal class DarkenSrc : PixelBlender { /// @@ -235,31 +213,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.DarkenSrc(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.DarkenSrc(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.DarkenSrc(background[i], source[i], amount[i]); + } } } + internal class LightenSrc : PixelBlender { /// @@ -274,31 +246,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.LightenSrc(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.LightenSrc(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.LightenSrc(background[i], source[i], amount[i]); + } } } + internal class OverlaySrc : PixelBlender { /// @@ -313,31 +279,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.OverlaySrc(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.OverlaySrc(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.OverlaySrc(background[i], source[i], amount[i]); + } } } + internal class HardLightSrc : PixelBlender { /// @@ -352,31 +312,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.HardLightSrc(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.HardLightSrc(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.HardLightSrc(background[i], source[i], amount[i]); + } } } + internal class NormalSrcAtop : PixelBlender { /// @@ -391,31 +345,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.NormalSrcAtop(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.NormalSrcAtop(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.NormalSrcAtop(background[i], source[i], amount[i]); + } } } + internal class MultiplySrcAtop : PixelBlender { /// @@ -430,31 +378,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.MultiplySrcAtop(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.MultiplySrcAtop(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.MultiplySrcAtop(background[i], source[i], amount[i]); + } } } + internal class AddSrcAtop : PixelBlender { /// @@ -469,31 +411,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.AddSrcAtop(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.AddSrcAtop(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.AddSrcAtop(background[i], source[i], amount[i]); + } } } + internal class SubtractSrcAtop : PixelBlender { /// @@ -508,31 +444,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.SubtractSrcAtop(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.SubtractSrcAtop(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.SubtractSrcAtop(background[i], source[i], amount[i]); + } } } + internal class ScreenSrcAtop : PixelBlender { /// @@ -547,31 +477,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.ScreenSrcAtop(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.ScreenSrcAtop(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.ScreenSrcAtop(background[i], source[i], amount[i]); + } } } + internal class DarkenSrcAtop : PixelBlender { /// @@ -586,31 +510,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.DarkenSrcAtop(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.DarkenSrcAtop(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.DarkenSrcAtop(background[i], source[i], amount[i]); + } } } + internal class LightenSrcAtop : PixelBlender { /// @@ -625,31 +543,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.LightenSrcAtop(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.LightenSrcAtop(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.LightenSrcAtop(background[i], source[i], amount[i]); + } } } + internal class OverlaySrcAtop : PixelBlender { /// @@ -664,31 +576,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.OverlaySrcAtop(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.OverlaySrcAtop(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.OverlaySrcAtop(background[i], source[i], amount[i]); + } } } + internal class HardLightSrcAtop : PixelBlender { /// @@ -703,31 +609,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.HardLightSrcAtop(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.HardLightSrcAtop(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.HardLightSrcAtop(background[i], source[i], amount[i]); + } } } + internal class NormalSrcOver : PixelBlender { /// @@ -742,31 +642,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.NormalSrcOver(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.NormalSrcOver(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.NormalSrcOver(background[i], source[i], amount[i]); + } } } + internal class MultiplySrcOver : PixelBlender { /// @@ -781,31 +675,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.MultiplySrcOver(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.MultiplySrcOver(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.MultiplySrcOver(background[i], source[i], amount[i]); + } } } + internal class AddSrcOver : PixelBlender { /// @@ -820,31 +708,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.AddSrcOver(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.AddSrcOver(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.AddSrcOver(background[i], source[i], amount[i]); + } } } + internal class SubtractSrcOver : PixelBlender { /// @@ -859,31 +741,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.SubtractSrcOver(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.SubtractSrcOver(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.SubtractSrcOver(background[i], source[i], amount[i]); + } } } + internal class ScreenSrcOver : PixelBlender { /// @@ -898,31 +774,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.ScreenSrcOver(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.ScreenSrcOver(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.ScreenSrcOver(background[i], source[i], amount[i]); + } } } + internal class DarkenSrcOver : PixelBlender { /// @@ -937,31 +807,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.DarkenSrcOver(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.DarkenSrcOver(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.DarkenSrcOver(background[i], source[i], amount[i]); + } } } + internal class LightenSrcOver : PixelBlender { /// @@ -976,31 +840,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.LightenSrcOver(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.LightenSrcOver(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.LightenSrcOver(background[i], source[i], amount[i]); + } } } + internal class OverlaySrcOver : PixelBlender { /// @@ -1015,31 +873,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.OverlaySrcOver(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.OverlaySrcOver(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.OverlaySrcOver(background[i], source[i], amount[i]); + } } } + internal class HardLightSrcOver : PixelBlender { /// @@ -1054,31 +906,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.HardLightSrcOver(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.HardLightSrcOver(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.HardLightSrcOver(background[i], source[i], amount[i]); + } } } + internal class NormalSrcIn : PixelBlender { /// @@ -1093,31 +939,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.NormalSrcIn(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.NormalSrcIn(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.NormalSrcIn(background[i], source[i], amount[i]); + } } } + internal class MultiplySrcIn : PixelBlender { /// @@ -1132,31 +972,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.MultiplySrcIn(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.MultiplySrcIn(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.MultiplySrcIn(background[i], source[i], amount[i]); + } } } + internal class AddSrcIn : PixelBlender { /// @@ -1171,31 +1005,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.AddSrcIn(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.AddSrcIn(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.AddSrcIn(background[i], source[i], amount[i]); + } } } + internal class SubtractSrcIn : PixelBlender { /// @@ -1210,31 +1038,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.SubtractSrcIn(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.SubtractSrcIn(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.SubtractSrcIn(background[i], source[i], amount[i]); + } } } + internal class ScreenSrcIn : PixelBlender { /// @@ -1249,31 +1071,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.ScreenSrcIn(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.ScreenSrcIn(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.ScreenSrcIn(background[i], source[i], amount[i]); + } } } + internal class DarkenSrcIn : PixelBlender { /// @@ -1288,31 +1104,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.DarkenSrcIn(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.DarkenSrcIn(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.DarkenSrcIn(background[i], source[i], amount[i]); + } } } + internal class LightenSrcIn : PixelBlender { /// @@ -1327,31 +1137,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.LightenSrcIn(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.LightenSrcIn(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.LightenSrcIn(background[i], source[i], amount[i]); + } } } + internal class OverlaySrcIn : PixelBlender { /// @@ -1366,31 +1170,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.OverlaySrcIn(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.OverlaySrcIn(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.OverlaySrcIn(background[i], source[i], amount[i]); + } } } + internal class HardLightSrcIn : PixelBlender { /// @@ -1405,31 +1203,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.HardLightSrcIn(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.HardLightSrcIn(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.HardLightSrcIn(background[i], source[i], amount[i]); + } } } + internal class NormalSrcOut : PixelBlender { /// @@ -1444,31 +1236,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.NormalSrcOut(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.NormalSrcOut(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.NormalSrcOut(background[i], source[i], amount[i]); + } } } + internal class MultiplySrcOut : PixelBlender { /// @@ -1483,31 +1269,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.MultiplySrcOut(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.MultiplySrcOut(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.MultiplySrcOut(background[i], source[i], amount[i]); + } } } + internal class AddSrcOut : PixelBlender { /// @@ -1522,31 +1302,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.AddSrcOut(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.AddSrcOut(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.AddSrcOut(background[i], source[i], amount[i]); + } } } + internal class SubtractSrcOut : PixelBlender { /// @@ -1561,31 +1335,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.SubtractSrcOut(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.SubtractSrcOut(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.SubtractSrcOut(background[i], source[i], amount[i]); + } } } + internal class ScreenSrcOut : PixelBlender { /// @@ -1600,31 +1368,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.ScreenSrcOut(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.ScreenSrcOut(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.ScreenSrcOut(background[i], source[i], amount[i]); + } } } + internal class DarkenSrcOut : PixelBlender { /// @@ -1639,31 +1401,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.DarkenSrcOut(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.DarkenSrcOut(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.DarkenSrcOut(background[i], source[i], amount[i]); + } } } + internal class LightenSrcOut : PixelBlender { /// @@ -1678,31 +1434,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.LightenSrcOut(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.LightenSrcOut(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.LightenSrcOut(background[i], source[i], amount[i]); + } } } + internal class OverlaySrcOut : PixelBlender { /// @@ -1717,31 +1467,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.OverlaySrcOut(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.OverlaySrcOut(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.OverlaySrcOut(background[i], source[i], amount[i]); + } } } + internal class HardLightSrcOut : PixelBlender { /// @@ -1756,31 +1500,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.HardLightSrcOut(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.HardLightSrcOut(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.HardLightSrcOut(background[i], source[i], amount[i]); + } } } + internal class NormalDest : PixelBlender { /// @@ -1795,31 +1533,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.NormalDest(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.NormalDest(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.NormalDest(background[i], source[i], amount[i]); + } } } + internal class MultiplyDest : PixelBlender { /// @@ -1834,31 +1566,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.MultiplyDest(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.MultiplyDest(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.MultiplyDest(background[i], source[i], amount[i]); + } } } + internal class AddDest : PixelBlender { /// @@ -1873,31 +1599,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.AddDest(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.AddDest(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.AddDest(background[i], source[i], amount[i]); + } } } + internal class SubtractDest : PixelBlender { /// @@ -1912,31 +1632,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.SubtractDest(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.SubtractDest(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.SubtractDest(background[i], source[i], amount[i]); + } } } + internal class ScreenDest : PixelBlender { /// @@ -1951,31 +1665,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.ScreenDest(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.ScreenDest(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.ScreenDest(background[i], source[i], amount[i]); + } } } + internal class DarkenDest : PixelBlender { /// @@ -1990,31 +1698,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.DarkenDest(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.DarkenDest(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.DarkenDest(background[i], source[i], amount[i]); + } } } + internal class LightenDest : PixelBlender { /// @@ -2029,31 +1731,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.LightenDest(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.LightenDest(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.LightenDest(background[i], source[i], amount[i]); + } } } + internal class OverlayDest : PixelBlender { /// @@ -2068,31 +1764,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.OverlayDest(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.OverlayDest(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.OverlayDest(background[i], source[i], amount[i]); + } } } + internal class HardLightDest : PixelBlender { /// @@ -2107,31 +1797,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.HardLightDest(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.HardLightDest(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.HardLightDest(background[i], source[i], amount[i]); + } } } + internal class NormalDestAtop : PixelBlender { /// @@ -2146,31 +1830,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.NormalDestAtop(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.NormalDestAtop(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.NormalDestAtop(background[i], source[i], amount[i]); + } } } + internal class MultiplyDestAtop : PixelBlender { /// @@ -2185,31 +1863,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.MultiplyDestAtop(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.MultiplyDestAtop(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.MultiplyDestAtop(background[i], source[i], amount[i]); + } } } + internal class AddDestAtop : PixelBlender { /// @@ -2224,31 +1896,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.AddDestAtop(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.AddDestAtop(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.AddDestAtop(background[i], source[i], amount[i]); + } } } + internal class SubtractDestAtop : PixelBlender { /// @@ -2263,31 +1929,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.SubtractDestAtop(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.SubtractDestAtop(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.SubtractDestAtop(background[i], source[i], amount[i]); + } } } + internal class ScreenDestAtop : PixelBlender { /// @@ -2302,31 +1962,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.ScreenDestAtop(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.ScreenDestAtop(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.ScreenDestAtop(background[i], source[i], amount[i]); + } } } + internal class DarkenDestAtop : PixelBlender { /// @@ -2341,31 +1995,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.DarkenDestAtop(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.DarkenDestAtop(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.DarkenDestAtop(background[i], source[i], amount[i]); + } } } + internal class LightenDestAtop : PixelBlender { /// @@ -2380,31 +2028,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.LightenDestAtop(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.LightenDestAtop(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.LightenDestAtop(background[i], source[i], amount[i]); + } } } + internal class OverlayDestAtop : PixelBlender { /// @@ -2419,31 +2061,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.OverlayDestAtop(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.OverlayDestAtop(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.OverlayDestAtop(background[i], source[i], amount[i]); + } } } + internal class HardLightDestAtop : PixelBlender { /// @@ -2458,31 +2094,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.HardLightDestAtop(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.HardLightDestAtop(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.HardLightDestAtop(background[i], source[i], amount[i]); + } } } + internal class NormalDestOver : PixelBlender { /// @@ -2497,31 +2127,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.NormalDestOver(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.NormalDestOver(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.NormalDestOver(background[i], source[i], amount[i]); + } } } + internal class MultiplyDestOver : PixelBlender { /// @@ -2536,31 +2160,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.MultiplyDestOver(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.MultiplyDestOver(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.MultiplyDestOver(background[i], source[i], amount[i]); + } } } + internal class AddDestOver : PixelBlender { /// @@ -2575,31 +2193,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.AddDestOver(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.AddDestOver(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.AddDestOver(background[i], source[i], amount[i]); + } } } + internal class SubtractDestOver : PixelBlender { /// @@ -2614,31 +2226,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.SubtractDestOver(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.SubtractDestOver(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.SubtractDestOver(background[i], source[i], amount[i]); + } } } + internal class ScreenDestOver : PixelBlender { /// @@ -2653,31 +2259,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.ScreenDestOver(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.ScreenDestOver(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.ScreenDestOver(background[i], source[i], amount[i]); + } } } + internal class DarkenDestOver : PixelBlender { /// @@ -2692,31 +2292,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.DarkenDestOver(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.DarkenDestOver(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.DarkenDestOver(background[i], source[i], amount[i]); + } } } + internal class LightenDestOver : PixelBlender { /// @@ -2731,31 +2325,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.LightenDestOver(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.LightenDestOver(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.LightenDestOver(background[i], source[i], amount[i]); + } } } + internal class OverlayDestOver : PixelBlender { /// @@ -2770,31 +2358,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.OverlayDestOver(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.OverlayDestOver(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.OverlayDestOver(background[i], source[i], amount[i]); + } } } + internal class HardLightDestOver : PixelBlender { /// @@ -2809,31 +2391,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.HardLightDestOver(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.HardLightDestOver(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.HardLightDestOver(background[i], source[i], amount[i]); + } } } + internal class NormalDestIn : PixelBlender { /// @@ -2848,31 +2424,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.NormalDestIn(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.NormalDestIn(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.NormalDestIn(background[i], source[i], amount[i]); + } } } + internal class MultiplyDestIn : PixelBlender { /// @@ -2887,31 +2457,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.MultiplyDestIn(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.MultiplyDestIn(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.MultiplyDestIn(background[i], source[i], amount[i]); + } } } + internal class AddDestIn : PixelBlender { /// @@ -2926,31 +2490,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.AddDestIn(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.AddDestIn(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.AddDestIn(background[i], source[i], amount[i]); + } } } + internal class SubtractDestIn : PixelBlender { /// @@ -2965,31 +2523,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.SubtractDestIn(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.SubtractDestIn(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.SubtractDestIn(background[i], source[i], amount[i]); + } } } + internal class ScreenDestIn : PixelBlender { /// @@ -3004,31 +2556,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.ScreenDestIn(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.ScreenDestIn(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.ScreenDestIn(background[i], source[i], amount[i]); + } } } + internal class DarkenDestIn : PixelBlender { /// @@ -3043,31 +2589,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.DarkenDestIn(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.DarkenDestIn(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.DarkenDestIn(background[i], source[i], amount[i]); + } } } + internal class LightenDestIn : PixelBlender { /// @@ -3082,31 +2622,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.LightenDestIn(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.LightenDestIn(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.LightenDestIn(background[i], source[i], amount[i]); + } } } + internal class OverlayDestIn : PixelBlender { /// @@ -3121,31 +2655,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.OverlayDestIn(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.OverlayDestIn(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.OverlayDestIn(background[i], source[i], amount[i]); + } } } + internal class HardLightDestIn : PixelBlender { /// @@ -3160,31 +2688,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.HardLightDestIn(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.HardLightDestIn(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.HardLightDestIn(background[i], source[i], amount[i]); + } } } + internal class NormalDestOut : PixelBlender { /// @@ -3199,31 +2721,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.NormalDestOut(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.NormalDestOut(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.NormalDestOut(background[i], source[i], amount[i]); + } } } + internal class MultiplyDestOut : PixelBlender { /// @@ -3238,31 +2754,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.MultiplyDestOut(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.MultiplyDestOut(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.MultiplyDestOut(background[i], source[i], amount[i]); + } } } + internal class AddDestOut : PixelBlender { /// @@ -3277,31 +2787,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.AddDestOut(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.AddDestOut(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.AddDestOut(background[i], source[i], amount[i]); + } } } + internal class SubtractDestOut : PixelBlender { /// @@ -3316,31 +2820,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.SubtractDestOut(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.SubtractDestOut(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.SubtractDestOut(background[i], source[i], amount[i]); + } } } + internal class ScreenDestOut : PixelBlender { /// @@ -3355,31 +2853,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.ScreenDestOut(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.ScreenDestOut(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.ScreenDestOut(background[i], source[i], amount[i]); + } } } + internal class DarkenDestOut : PixelBlender { /// @@ -3394,31 +2886,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.DarkenDestOut(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.DarkenDestOut(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.DarkenDestOut(background[i], source[i], amount[i]); + } } } + internal class LightenDestOut : PixelBlender { /// @@ -3433,31 +2919,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.LightenDestOut(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.LightenDestOut(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.LightenDestOut(background[i], source[i], amount[i]); + } } } + internal class OverlayDestOut : PixelBlender { /// @@ -3472,31 +2952,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.OverlayDestOut(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.OverlayDestOut(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.OverlayDestOut(background[i], source[i], amount[i]); + } } } + internal class HardLightDestOut : PixelBlender { /// @@ -3511,31 +2985,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.HardLightDestOut(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.HardLightDestOut(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.HardLightDestOut(background[i], source[i], amount[i]); + } } } + internal class NormalClear : PixelBlender { /// @@ -3550,31 +3018,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.NormalClear(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.NormalClear(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.NormalClear(background[i], source[i], amount[i]); + } } } + internal class MultiplyClear : PixelBlender { /// @@ -3589,31 +3051,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.MultiplyClear(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.MultiplyClear(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.MultiplyClear(background[i], source[i], amount[i]); + } } } + internal class AddClear : PixelBlender { /// @@ -3628,31 +3084,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.AddClear(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.AddClear(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.AddClear(background[i], source[i], amount[i]); + } } } + internal class SubtractClear : PixelBlender { /// @@ -3667,31 +3117,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.SubtractClear(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.SubtractClear(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.SubtractClear(background[i], source[i], amount[i]); + } } } + internal class ScreenClear : PixelBlender { /// @@ -3706,31 +3150,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.ScreenClear(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.ScreenClear(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.ScreenClear(background[i], source[i], amount[i]); + } } } + internal class DarkenClear : PixelBlender { /// @@ -3745,31 +3183,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.DarkenClear(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.DarkenClear(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.DarkenClear(background[i], source[i], amount[i]); + } } } + internal class LightenClear : PixelBlender { /// @@ -3784,31 +3216,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.LightenClear(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.LightenClear(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.LightenClear(background[i], source[i], amount[i]); + } } } + internal class OverlayClear : PixelBlender { /// @@ -3823,31 +3249,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.OverlayClear(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.OverlayClear(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.OverlayClear(background[i], source[i], amount[i]); + } } } + internal class HardLightClear : PixelBlender { /// @@ -3862,31 +3282,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.HardLightClear(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.HardLightClear(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.HardLightClear(background[i], source[i], amount[i]); + } } } + internal class NormalXor : PixelBlender { /// @@ -3901,31 +3315,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.NormalXor(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.NormalXor(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.NormalXor(background[i], source[i], amount[i]); + } } } + internal class MultiplyXor : PixelBlender { /// @@ -3940,31 +3348,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.MultiplyXor(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.MultiplyXor(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.MultiplyXor(background[i], source[i], amount[i]); + } } } + internal class AddXor : PixelBlender { /// @@ -3979,31 +3381,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.AddXor(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.AddXor(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.AddXor(background[i], source[i], amount[i]); + } } } + internal class SubtractXor : PixelBlender { /// @@ -4018,31 +3414,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.SubtractXor(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.SubtractXor(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.SubtractXor(background[i], source[i], amount[i]); + } } } + internal class ScreenXor : PixelBlender { /// @@ -4057,31 +3447,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.ScreenXor(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.ScreenXor(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.ScreenXor(background[i], source[i], amount[i]); + } } } + internal class DarkenXor : PixelBlender { /// @@ -4096,31 +3480,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.DarkenXor(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.DarkenXor(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.DarkenXor(background[i], source[i], amount[i]); + } } } + internal class LightenXor : PixelBlender { /// @@ -4135,31 +3513,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.LightenXor(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.LightenXor(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.LightenXor(background[i], source[i], amount[i]); + } } } + internal class OverlayXor : PixelBlender { /// @@ -4174,31 +3546,25 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.OverlayXor(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.OverlayXor(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.OverlayXor(background[i], source[i], amount[i]); + } } } + internal class HardLightXor : PixelBlender { /// @@ -4213,30 +3579,24 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.HardLightXor(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.HardLightXor(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.HardLightXor(background[i], source[i], amount[i]); + } } } + } } \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.tt b/src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.tt index 34fe4d4cda..85dbd7091e 100644 --- a/src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.tt +++ b/src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.tt @@ -12,9 +12,11 @@ // Licensed under the Apache License, Version 2.0. // -using System; -using System.Numerics; -using System.Buffers; +using System; +using System.Numerics; +using System.Buffers; + +using SixLabors.ImageSharp.Memory; using SixLabors.Memory; namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders @@ -82,28 +84,21 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders } /// - public override void Blend(MemoryAllocator memoryManager, Span destination, Span background, Span source, Span amount) + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - 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 (IMemoryOwner buffer = memoryManager.Allocate(destination.Length * 3)) + for (int i = 0; i < destination.Length; i++) { - 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.<#=blender_composer#>(backgroundSpan[i], sourceSpan[i], amount[i]); - } + destination[i] = PorterDuffFunctions.<#=blender_composer#>(background[i], source[i], amount); + } + } - PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); - } + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.<#=blender_composer#>(background[i], source[i], amount[i]); + } } } diff --git a/src/ImageSharp/PixelFormats/PixelBlender{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelBlender{TPixel}.cs index b8b97ea0a4..0180ef36c6 100644 --- a/src/ImageSharp/PixelFormats/PixelBlender{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/PixelBlender{TPixel}.cs @@ -2,6 +2,9 @@ // Licensed under the Apache License, Version 2.0. using System; +using System.Buffers; +using System.Numerics; +using SixLabors.ImageSharp.Memory; using SixLabors.Memory; namespace SixLabors.ImageSharp.PixelFormats @@ -23,19 +26,130 @@ namespace SixLabors.ImageSharp.PixelFormats /// At amount = 0, "from" is returned, at amount = 1, "to" is returned. /// /// The final pixel value after composition - public abstract TPixel Blend(TPixel background, TPixel source, float amount); - - /// - /// Blend 2 pixels together. - /// - /// The - /// The destination span. - /// The background span. - /// The source span. + public abstract TPixel Blend(TPixel background, TPixel source, float amount); + + /// + /// Blend 2 rows together. + /// + /// destination span + /// the background span + /// the source span /// /// A value between 0 and 1 indicating the weight of the second source vector. /// At amount = 0, "from" is returned, at amount = 1, "to" is returned. - /// - public abstract void Blend(MemoryAllocator memoryAllocator, Span destination, Span background, Span source, Span amount); + /// + protected abstract void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount); + + /// + /// Blend 2 rows together. + /// + /// destination span + /// the background span + /// the source span + /// + /// A span with values between 0 and 1 indicating the weight of the second source vector. + /// At amount = 0, "from" is returned, at amount = 1, "to" is returned. + /// + protected abstract void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount); + + /// + /// Blends 2 rows together + /// + /// the pixel format of the source span + /// memory manager to use internally + /// the destination span + /// the background span + /// the source span + /// + /// A span with values between 0 and 1 indicating the weight of the second source vector. + /// At amount = 0, "from" is returned, at amount = 1, "to" is returned. + /// + public void Blend(MemoryAllocator memoryManager, Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + where TPixelSrc : 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 (IMemoryOwner buffer = memoryManager.Allocate(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); + + this.BlendFunction(destinationSpan, backgroundSpan, sourceSpan, amount); + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + + /// + /// Blends 2 rows together + /// + /// the pixel format of the source span + /// memory manager to use internally + /// the destination span + /// the background span + /// the source span + /// + /// A value between 0 and 1 indicating the weight of the second source vector. + /// At amount = 0, "from" is returned, at amount = 1, "to" is returned. + /// + public void Blend(MemoryAllocator memoryManager, Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + where TPixelSrc : struct, IPixel + { + Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); + Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); + Guard.MustBeBetweenOrEqualTo(amount, 0, 1, nameof(amount)); + + using (IMemoryOwner buffer = memoryManager.Allocate(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); + + this.BlendFunction(destinationSpan, backgroundSpan, sourceSpan, amount); + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } + + /// + /// Blends 2 rows together + /// + /// memory manager to use internally + /// the destination span + /// the background span + /// the source span + /// + /// A span with values between 0 and 1 indicating the weight of the second source vector. + /// At amount = 0, "from" is returned, at amount = 1, "to" is returned. + /// + public void Blend(MemoryAllocator memoryManager, Span destination, ReadOnlySpan background, ReadOnlySpan source, ReadOnlySpan amount) + { + 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 (IMemoryOwner buffer = memoryManager.Allocate(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); + + this.BlendFunction(destinationSpan, backgroundSpan, sourceSpan, amount); + + PixelOperations.Instance.PackFromVector4(destinationSpan, destination, destination.Length); + } + } } }