diff --git a/.gitattributes b/.gitattributes index 38abe0d4a..b9a9ddd4c 100644 --- a/.gitattributes +++ b/.gitattributes @@ -44,7 +44,7 @@ *.sql text eol=lf *.svg text eol=lf *.targets text eol=lf -*.tt text eol=lf +*.tt text eol=crlf *.ttinclude text eol=crlf *.txt text eol=lf *.vb text eol=lf diff --git a/.gitignore b/.gitignore index 494281897..d8f376a41 100644 --- a/.gitignore +++ b/.gitignore @@ -204,8 +204,6 @@ FakesAssemblies/ **/node_modules **/node_modules/* -**/Images/ActualOutput -**/Images/ReferenceOutput # ASP.NET 5 project.lock.json @@ -218,7 +216,8 @@ artifacts/ *.csproj.bak #CodeCoverage -**/CodeCoverage/* -docs/ -/samples/AvatarWithRoundedCorner/output /ImageSharp.Coverage.xml + +# Tests +**/Images/ActualOutput +**/Images/ReferenceOutput diff --git a/README.md b/README.md index a5c3457fa..3c343ad13 100644 --- a/README.md +++ b/README.md @@ -118,12 +118,18 @@ Alternatively, you can work from command line and/or with a lightweight editor o - [Visual Studio Code](https://code.visualstudio.com/) with [C# Extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode.csharp) - [.NET Core](https://www.microsoft.com/net/core#linuxubuntu) -To clone ImageSharp locally, click the "Clone in Windows" button above or run the following git commands: +To clone ImageSharp locally, click the "Clone in [YOUR_OS]" button above or run the following git commands: ```bash git clone https://github.com/SixLabors/ImageSharp ``` +If working with Windows please ensure that you have enabled log file paths in git (run as Administrator). + +```bash +git config --system core.longpaths true +``` + ### Submodules This repository contains [git submodules](https://blog.github.com/2016-02-01-working-with-submodules/). To add the submodules to the project, navigate to the repository root and type: diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs index 54b7315b2..889b7b567 100644 --- a/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs +++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs @@ -1,99 +1,99 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System.Buffers; -using System.Threading.Tasks; - -using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.Memory; -using SixLabors.Primitives; - -namespace SixLabors.ImageSharp.Processing.Processors.Drawing -{ - /// - /// Combines two images together by blending the pixels. - /// - public class DrawImageProcessor : IImageProcessor - { - /// - /// Initializes a new instance of the class. - /// - /// The image to blend. - /// 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. - public DrawImageProcessor( - Image image, - Point location, - PixelColorBlendingMode colorBlendingMode, - PixelAlphaCompositionMode alphaCompositionMode, - float opacity) - { - this.Image = image; - this.Location = location; - this.ColorBlendingMode = colorBlendingMode; - this.AlphaCompositionMode = alphaCompositionMode; - this.Opacity = opacity; - } - - /// - /// Gets the image to blend. - /// - public Image Image { get; } - - /// - /// Gets the location to draw the blended image. - /// - public Point Location { get; } - - /// - /// Gets the blending mode to use when drawing the image. - /// - public PixelColorBlendingMode ColorBlendingMode { get; } - - /// - /// Gets the Alpha blending mode to use when drawing the image. - /// - public PixelAlphaCompositionMode AlphaCompositionMode { get; } - - /// - /// Gets the opacity of the image to blend. - /// - public float Opacity { get; } - - /// - public IImageProcessor CreatePixelSpecificProcessor() - where TPixelBg : struct, IPixel - { - var visitor = new ProcessorFactoryVisitor(this); - this.Image.AcceptVisitor(visitor); - return visitor.Result; - } - - private class ProcessorFactoryVisitor : IImageVisitor - where TPixelBg : struct, IPixel - { - private readonly DrawImageProcessor definition; - - public ProcessorFactoryVisitor(DrawImageProcessor definition) - { - this.definition = definition; - } - - public IImageProcessor Result { get; private set; } - - public void Visit(Image image) - where TPixelFg : struct, IPixel - { - this.Result = new DrawImageProcessor( - image, - this.definition.Location, - this.definition.ColorBlendingMode, - this.definition.AlphaCompositionMode, - this.definition.Opacity); - } - } - } +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System.Buffers; +using System.Threading.Tasks; + +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Memory; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Drawing +{ + /// + /// Combines two images together by blending the pixels. + /// + public class DrawImageProcessor : IImageProcessor + { + /// + /// Initializes a new instance of the class. + /// + /// The image to blend. + /// 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. + public DrawImageProcessor( + Image image, + Point location, + PixelColorBlendingMode colorBlendingMode, + PixelAlphaCompositionMode alphaCompositionMode, + float opacity) + { + this.Image = image; + this.Location = location; + this.ColorBlendingMode = colorBlendingMode; + this.AlphaCompositionMode = alphaCompositionMode; + this.Opacity = opacity; + } + + /// + /// Gets the image to blend. + /// + public Image Image { get; } + + /// + /// Gets the location to draw the blended image. + /// + public Point Location { get; } + + /// + /// Gets the blending mode to use when drawing the image. + /// + public PixelColorBlendingMode ColorBlendingMode { get; } + + /// + /// Gets the Alpha blending mode to use when drawing the image. + /// + public PixelAlphaCompositionMode AlphaCompositionMode { get; } + + /// + /// Gets the opacity of the image to blend. + /// + public float Opacity { get; } + + /// + public IImageProcessor CreatePixelSpecificProcessor() + where TPixelBg : struct, IPixel + { + var visitor = new ProcessorFactoryVisitor(this); + this.Image.AcceptVisitor(visitor); + return visitor.Result; + } + + private class ProcessorFactoryVisitor : IImageVisitor + where TPixelBg : struct, IPixel + { + private readonly DrawImageProcessor definition; + + public ProcessorFactoryVisitor(DrawImageProcessor definition) + { + this.definition = definition; + } + + public IImageProcessor Result { get; private set; } + + public void Visit(Image image) + where TPixelFg : struct, IPixel + { + this.Result = new DrawImageProcessor( + image, + this.definition.Location, + this.definition.ColorBlendingMode, + this.definition.AlphaCompositionMode, + this.definition.Opacity); + } + } + } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor.cs index d6254c7cf..0f72a4692 100644 --- a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor.cs +++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor.cs @@ -1,45 +1,45 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System.Threading.Tasks; - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.Memory; - -namespace SixLabors.ImageSharp.Processing.Processors.Drawing -{ - /// - /// Defines a processor to fill an with the given - /// using blending defined by the given . - /// - public class FillProcessor : IImageProcessor - { - /// - /// Initializes a new instance of the class. - /// - /// The brush to use for filling. - /// The defining how to blend the brush pixels over the image pixels. - public FillProcessor(IBrush brush, GraphicsOptions options) - { - this.Brush = brush; - this.Options = options; - } - - /// - /// Gets the used for filling the destination image. - /// - public IBrush Brush { get; } - - /// - /// Gets the defining how to blend the brush pixels over the image pixels. - /// - public GraphicsOptions Options { get; } - - /// - public IImageProcessor CreatePixelSpecificProcessor() - where TPixel : struct, IPixel - { - return new FillProcessor(this); - } - } +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System.Threading.Tasks; + +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Memory; + +namespace SixLabors.ImageSharp.Processing.Processors.Drawing +{ + /// + /// Defines a processor to fill an with the given + /// using blending defined by the given . + /// + public class FillProcessor : IImageProcessor + { + /// + /// Initializes a new instance of the class. + /// + /// The brush to use for filling. + /// The defining how to blend the brush pixels over the image pixels. + public FillProcessor(IBrush brush, GraphicsOptions options) + { + this.Brush = brush; + this.Options = options; + } + + /// + /// Gets the used for filling the destination image. + /// + public IBrush Brush { get; } + + /// + /// Gets the defining how to blend the brush pixels over the image pixels. + /// + public GraphicsOptions Options { get; } + + /// + public IImageProcessor CreatePixelSpecificProcessor() + where TPixel : struct, IPixel + { + return new FillProcessor(this); + } + } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/TextGraphicsOptions.cs b/src/ImageSharp.Drawing/Processing/TextGraphicsOptions.cs index 7f7332a57..6c140be72 100644 --- a/src/ImageSharp.Drawing/Processing/TextGraphicsOptions.cs +++ b/src/ImageSharp.Drawing/Processing/TextGraphicsOptions.cs @@ -1,163 +1,163 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.Fonts; -using SixLabors.ImageSharp.PixelFormats; - -namespace SixLabors.ImageSharp.Processing -{ - /// - /// Options for influencing the drawing functions. - /// - public struct TextGraphicsOptions - { - private const int DefaultTextDpi = 72; - - /// - /// Represents the default . - /// - public static readonly TextGraphicsOptions Default = new TextGraphicsOptions(true); - - private float? blendPercentage; - - private int? antialiasSubpixelDepth; - - private bool? antialias; - - private bool? applyKerning; - - private float? tabWidth; - - private float? dpiX; - - private float? dpiY; - - private HorizontalAlignment? horizontalAlignment; - - private VerticalAlignment? verticalAlignment; - - /// - /// Initializes a new instance of the struct. - /// - /// If set to true [enable antialiasing]. - public TextGraphicsOptions(bool enableAntialiasing) - { - this.applyKerning = true; - this.tabWidth = 4; - this.WrapTextWidth = 0; - this.horizontalAlignment = HorizontalAlignment.Left; - this.verticalAlignment = VerticalAlignment.Top; - - this.antialiasSubpixelDepth = 16; - this.ColorBlendingMode = PixelColorBlendingMode.Normal; - this.AlphaCompositionMode = PixelAlphaCompositionMode.SrcOver; - this.blendPercentage = 1; - this.antialias = enableAntialiasing; - this.dpiX = DefaultTextDpi; - this.dpiY = DefaultTextDpi; - } - - /// - /// Gets or sets a value indicating whether antialiasing should be applied. - /// - public bool Antialias { get => this.antialias ?? true; set => this.antialias = value; } - - /// - /// Gets or sets a value indicating the number of subpixels to use while rendering with antialiasing enabled. - /// - public int AntialiasSubpixelDepth { get => this.antialiasSubpixelDepth ?? 16; set => this.antialiasSubpixelDepth = value; } - - /// - /// Gets or sets a value indicating the blending percentage to apply to the drawing operation - /// - public float BlendPercentage { get => (this.blendPercentage ?? 1).Clamp(0, 1); set => this.blendPercentage = value; } - - // In the future we could expose a PixelBlender directly on here - // or some forms of PixelBlender factory for each pixel type. Will need - // some API thought post V1. - - /// - /// Gets or sets a value indicating the color blending percentage to apply to the drawing operation - /// - public PixelColorBlendingMode ColorBlendingMode { get; set; } - - /// - /// Gets or sets a value indicating the color blending percentage to apply to the drawing operation - /// - public PixelAlphaCompositionMode AlphaCompositionMode { get; set; } - - /// - /// Gets or sets a value indicating whether the text should be drawing with kerning enabled. - /// - public bool ApplyKerning { get => this.applyKerning ?? true; set => this.applyKerning = value; } - - /// - /// Gets or sets a value indicating the number of space widths a tab should lock to. - /// - public float TabWidth { get => this.tabWidth ?? 4; set => this.tabWidth = value; } - - /// - /// Gets or sets a value indicating if greater than zero determine the width at which text should wrap. - /// - public float WrapTextWidth { get; set; } - - /// - /// Gets or sets a value indicating the DPI to render text along the X axis. - /// - public float DpiX { get => this.dpiX ?? DefaultTextDpi; set => this.dpiX = value; } - - /// - /// Gets or sets a value indicating the DPI to render text along the Y axis. - /// - public float DpiY { get => this.dpiY ?? DefaultTextDpi; set => this.dpiY = value; } - - /// - /// Gets or sets a value indicating how to align the text relative to the rendering space. - /// If is greater than zero it will align relative to the space - /// defined by the location and width, if equals zero, and thus - /// wrapping disabled, then the alignment is relative to the drawing location. - /// - public HorizontalAlignment HorizontalAlignment { get => this.horizontalAlignment ?? HorizontalAlignment.Left; set => this.horizontalAlignment = value; } - - /// - /// Gets or sets a value indicating how to align the text relative to the rendering space. - /// - public VerticalAlignment VerticalAlignment { get => this.verticalAlignment ?? VerticalAlignment.Top; set => this.verticalAlignment = value; } - - /// - /// Performs an implicit conversion from to . - /// - /// The options. - /// - /// The result of the conversion. - /// - public static implicit operator TextGraphicsOptions(GraphicsOptions options) - { - return new TextGraphicsOptions(options.Antialias) - { - AntialiasSubpixelDepth = options.AntialiasSubpixelDepth, - blendPercentage = options.BlendPercentage, - ColorBlendingMode = options.ColorBlendingMode, - AlphaCompositionMode = options.AlphaCompositionMode - }; - } - - /// - /// Performs an explicit conversion from to . - /// - /// The options. - /// - /// The result of the conversion. - /// - public static explicit operator GraphicsOptions(TextGraphicsOptions options) - { - return new GraphicsOptions(options.Antialias) - { - AntialiasSubpixelDepth = options.AntialiasSubpixelDepth, - ColorBlendingMode = options.ColorBlendingMode, - AlphaCompositionMode = options.AlphaCompositionMode, - BlendPercentage = options.BlendPercentage - }; - } - } +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.Fonts; +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp.Processing +{ + /// + /// Options for influencing the drawing functions. + /// + public struct TextGraphicsOptions + { + private const int DefaultTextDpi = 72; + + /// + /// Represents the default . + /// + public static readonly TextGraphicsOptions Default = new TextGraphicsOptions(true); + + private float? blendPercentage; + + private int? antialiasSubpixelDepth; + + private bool? antialias; + + private bool? applyKerning; + + private float? tabWidth; + + private float? dpiX; + + private float? dpiY; + + private HorizontalAlignment? horizontalAlignment; + + private VerticalAlignment? verticalAlignment; + + /// + /// Initializes a new instance of the struct. + /// + /// If set to true [enable antialiasing]. + public TextGraphicsOptions(bool enableAntialiasing) + { + this.applyKerning = true; + this.tabWidth = 4; + this.WrapTextWidth = 0; + this.horizontalAlignment = HorizontalAlignment.Left; + this.verticalAlignment = VerticalAlignment.Top; + + this.antialiasSubpixelDepth = 16; + this.ColorBlendingMode = PixelColorBlendingMode.Normal; + this.AlphaCompositionMode = PixelAlphaCompositionMode.SrcOver; + this.blendPercentage = 1; + this.antialias = enableAntialiasing; + this.dpiX = DefaultTextDpi; + this.dpiY = DefaultTextDpi; + } + + /// + /// Gets or sets a value indicating whether antialiasing should be applied. + /// + public bool Antialias { get => this.antialias ?? true; set => this.antialias = value; } + + /// + /// Gets or sets a value indicating the number of subpixels to use while rendering with antialiasing enabled. + /// + public int AntialiasSubpixelDepth { get => this.antialiasSubpixelDepth ?? 16; set => this.antialiasSubpixelDepth = value; } + + /// + /// Gets or sets a value indicating the blending percentage to apply to the drawing operation + /// + public float BlendPercentage { get => (this.blendPercentage ?? 1).Clamp(0, 1); set => this.blendPercentage = value; } + + // In the future we could expose a PixelBlender directly on here + // or some forms of PixelBlender factory for each pixel type. Will need + // some API thought post V1. + + /// + /// Gets or sets a value indicating the color blending percentage to apply to the drawing operation + /// + public PixelColorBlendingMode ColorBlendingMode { get; set; } + + /// + /// Gets or sets a value indicating the color blending percentage to apply to the drawing operation + /// + public PixelAlphaCompositionMode AlphaCompositionMode { get; set; } + + /// + /// Gets or sets a value indicating whether the text should be drawing with kerning enabled. + /// + public bool ApplyKerning { get => this.applyKerning ?? true; set => this.applyKerning = value; } + + /// + /// Gets or sets a value indicating the number of space widths a tab should lock to. + /// + public float TabWidth { get => this.tabWidth ?? 4; set => this.tabWidth = value; } + + /// + /// Gets or sets a value indicating if greater than zero determine the width at which text should wrap. + /// + public float WrapTextWidth { get; set; } + + /// + /// Gets or sets a value indicating the DPI to render text along the X axis. + /// + public float DpiX { get => this.dpiX ?? DefaultTextDpi; set => this.dpiX = value; } + + /// + /// Gets or sets a value indicating the DPI to render text along the Y axis. + /// + public float DpiY { get => this.dpiY ?? DefaultTextDpi; set => this.dpiY = value; } + + /// + /// Gets or sets a value indicating how to align the text relative to the rendering space. + /// If is greater than zero it will align relative to the space + /// defined by the location and width, if equals zero, and thus + /// wrapping disabled, then the alignment is relative to the drawing location. + /// + public HorizontalAlignment HorizontalAlignment { get => this.horizontalAlignment ?? HorizontalAlignment.Left; set => this.horizontalAlignment = value; } + + /// + /// Gets or sets a value indicating how to align the text relative to the rendering space. + /// + public VerticalAlignment VerticalAlignment { get => this.verticalAlignment ?? VerticalAlignment.Top; set => this.verticalAlignment = value; } + + /// + /// Performs an implicit conversion from to . + /// + /// The options. + /// + /// The result of the conversion. + /// + public static implicit operator TextGraphicsOptions(GraphicsOptions options) + { + return new TextGraphicsOptions(options.Antialias) + { + AntialiasSubpixelDepth = options.AntialiasSubpixelDepth, + blendPercentage = options.BlendPercentage, + ColorBlendingMode = options.ColorBlendingMode, + AlphaCompositionMode = options.AlphaCompositionMode + }; + } + + /// + /// Performs an explicit conversion from to . + /// + /// The options. + /// + /// The result of the conversion. + /// + public static explicit operator GraphicsOptions(TextGraphicsOptions options) + { + return new GraphicsOptions(options.Antialias) + { + AntialiasSubpixelDepth = options.AntialiasSubpixelDepth, + ColorBlendingMode = options.ColorBlendingMode, + AlphaCompositionMode = options.AlphaCompositionMode, + BlendPercentage = options.BlendPercentage + }; + } + } } \ No newline at end of file diff --git a/src/ImageSharp/Configuration.cs b/src/ImageSharp/Configuration.cs index 4e8284c2c..0d44db8d8 100644 --- a/src/ImageSharp/Configuration.cs +++ b/src/ImageSharp/Configuration.cs @@ -1,164 +1,164 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Collections.Generic; -using SixLabors.ImageSharp.Formats; -using SixLabors.ImageSharp.Formats.Bmp; -using SixLabors.ImageSharp.Formats.Gif; -using SixLabors.ImageSharp.Formats.Jpeg; -using SixLabors.ImageSharp.Formats.Png; -using SixLabors.ImageSharp.IO; -using SixLabors.ImageSharp.Processing; -using SixLabors.Memory; - -namespace SixLabors.ImageSharp -{ - /// - /// Provides configuration code which allows altering default behaviour or extending the library. - /// - public sealed class Configuration - { - /// - /// A lazily initialized configuration default instance. - /// - private static readonly Lazy Lazy = new Lazy(CreateDefaultInstance); - - private int maxDegreeOfParallelism = Environment.ProcessorCount; - - /// - /// Initializes a new instance of the class. - /// - public Configuration() - { - } - - /// - /// Initializes a new instance of the class. - /// - /// A collection of configuration modules to register - public Configuration(params IConfigurationModule[] configurationModules) - { - if (configurationModules != null) - { - foreach (IConfigurationModule p in configurationModules) - { - p.Configure(this); - } - } - } - - /// - /// Gets the default instance. - /// - public static Configuration Default { get; } = Lazy.Value; - - /// - /// Gets or sets the maximum number of concurrent tasks enabled in ImageSharp algorithms - /// configured with this instance. - /// Initialized with by default. - /// - public int MaxDegreeOfParallelism - { - get => this.maxDegreeOfParallelism; - set - { - if (value <= 0) - { - throw new ArgumentOutOfRangeException(nameof(this.MaxDegreeOfParallelism)); - } - - this.maxDegreeOfParallelism = value; - } - } - - /// - /// Gets the currently registered s. - /// - public IEnumerable ImageFormats => this.ImageFormatsManager.ImageFormats; - - /// - /// Gets or sets the position in a stream to use for reading when using a seekable stream as an image data source. - /// - public ReadOrigin ReadOrigin { get; set; } = ReadOrigin.Current; - - /// - /// Gets or sets the that is currently in use. - /// - public ImageFormatManager ImageFormatsManager { get; set; } = new ImageFormatManager(); - - /// - /// Gets or sets the that is currently in use. - /// - public MemoryAllocator MemoryAllocator { get; set; } = ArrayPoolMemoryAllocator.CreateDefault(); - - /// - /// Gets the maximum header size of all the formats. - /// - internal int MaxHeaderSize => this.ImageFormatsManager.MaxHeaderSize; - - /// - /// Gets or sets the filesystem helper for accessing the local file system. - /// - internal IFileSystem FileSystem { get; set; } = new LocalFileSystem(); - - /// - /// Gets or sets the working buffer size hint for image processors. - /// The default value is 1MB. - /// - /// - /// Currently only used by Resize. - /// - internal int WorkingBufferSizeHintInBytes { get; set; } = 1 * 1024 * 1024; - - /// - /// Gets or sets the image operations provider factory. - /// - internal IImageProcessingContextFactory ImageOperationsProvider { get; set; } = new DefaultImageOperationsProviderFactory(); - - /// - /// Registers a new format provider. - /// - /// The configuration provider to call configure on. - public void Configure(IConfigurationModule configuration) - { - Guard.NotNull(configuration, nameof(configuration)); - configuration.Configure(this); - } - - /// - /// Creates a shallow copy of the . - /// - /// A new configuration instance. - public Configuration Clone() - { - return new Configuration - { - MaxDegreeOfParallelism = this.MaxDegreeOfParallelism, - ImageFormatsManager = this.ImageFormatsManager, - MemoryAllocator = this.MemoryAllocator, - ImageOperationsProvider = this.ImageOperationsProvider, - ReadOrigin = this.ReadOrigin, - FileSystem = this.FileSystem, - WorkingBufferSizeHintInBytes = this.WorkingBufferSizeHintInBytes, - }; - } - - /// - /// Creates the default instance with the following s preregistered: - /// - /// - /// - /// . - /// - /// The default configuration of . - internal static Configuration CreateDefaultInstance() - { - return new Configuration( - new PngConfigurationModule(), - new JpegConfigurationModule(), - new GifConfigurationModule(), - new BmpConfigurationModule()); - } - } +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Collections.Generic; +using SixLabors.ImageSharp.Formats; +using SixLabors.ImageSharp.Formats.Bmp; +using SixLabors.ImageSharp.Formats.Gif; +using SixLabors.ImageSharp.Formats.Jpeg; +using SixLabors.ImageSharp.Formats.Png; +using SixLabors.ImageSharp.IO; +using SixLabors.ImageSharp.Processing; +using SixLabors.Memory; + +namespace SixLabors.ImageSharp +{ + /// + /// Provides configuration code which allows altering default behaviour or extending the library. + /// + public sealed class Configuration + { + /// + /// A lazily initialized configuration default instance. + /// + private static readonly Lazy Lazy = new Lazy(CreateDefaultInstance); + + private int maxDegreeOfParallelism = Environment.ProcessorCount; + + /// + /// Initializes a new instance of the class. + /// + public Configuration() + { + } + + /// + /// Initializes a new instance of the class. + /// + /// A collection of configuration modules to register + public Configuration(params IConfigurationModule[] configurationModules) + { + if (configurationModules != null) + { + foreach (IConfigurationModule p in configurationModules) + { + p.Configure(this); + } + } + } + + /// + /// Gets the default instance. + /// + public static Configuration Default { get; } = Lazy.Value; + + /// + /// Gets or sets the maximum number of concurrent tasks enabled in ImageSharp algorithms + /// configured with this instance. + /// Initialized with by default. + /// + public int MaxDegreeOfParallelism + { + get => this.maxDegreeOfParallelism; + set + { + if (value <= 0) + { + throw new ArgumentOutOfRangeException(nameof(this.MaxDegreeOfParallelism)); + } + + this.maxDegreeOfParallelism = value; + } + } + + /// + /// Gets the currently registered s. + /// + public IEnumerable ImageFormats => this.ImageFormatsManager.ImageFormats; + + /// + /// Gets or sets the position in a stream to use for reading when using a seekable stream as an image data source. + /// + public ReadOrigin ReadOrigin { get; set; } = ReadOrigin.Current; + + /// + /// Gets or sets the that is currently in use. + /// + public ImageFormatManager ImageFormatsManager { get; set; } = new ImageFormatManager(); + + /// + /// Gets or sets the that is currently in use. + /// + public MemoryAllocator MemoryAllocator { get; set; } = ArrayPoolMemoryAllocator.CreateDefault(); + + /// + /// Gets the maximum header size of all the formats. + /// + internal int MaxHeaderSize => this.ImageFormatsManager.MaxHeaderSize; + + /// + /// Gets or sets the filesystem helper for accessing the local file system. + /// + internal IFileSystem FileSystem { get; set; } = new LocalFileSystem(); + + /// + /// Gets or sets the working buffer size hint for image processors. + /// The default value is 1MB. + /// + /// + /// Currently only used by Resize. + /// + internal int WorkingBufferSizeHintInBytes { get; set; } = 1 * 1024 * 1024; + + /// + /// Gets or sets the image operations provider factory. + /// + internal IImageProcessingContextFactory ImageOperationsProvider { get; set; } = new DefaultImageOperationsProviderFactory(); + + /// + /// Registers a new format provider. + /// + /// The configuration provider to call configure on. + public void Configure(IConfigurationModule configuration) + { + Guard.NotNull(configuration, nameof(configuration)); + configuration.Configure(this); + } + + /// + /// Creates a shallow copy of the . + /// + /// A new configuration instance. + public Configuration Clone() + { + return new Configuration + { + MaxDegreeOfParallelism = this.MaxDegreeOfParallelism, + ImageFormatsManager = this.ImageFormatsManager, + MemoryAllocator = this.MemoryAllocator, + ImageOperationsProvider = this.ImageOperationsProvider, + ReadOrigin = this.ReadOrigin, + FileSystem = this.FileSystem, + WorkingBufferSizeHintInBytes = this.WorkingBufferSizeHintInBytes, + }; + } + + /// + /// Creates the default instance with the following s preregistered: + /// + /// + /// + /// . + /// + /// The default configuration of . + internal static Configuration CreateDefaultInstance() + { + return new Configuration( + new PngConfigurationModule(), + new JpegConfigurationModule(), + new GifConfigurationModule(), + new BmpConfigurationModule()); + } + } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/ImageFormatManager.cs b/src/ImageSharp/Formats/ImageFormatManager.cs index e62805d47..e34155706 100644 --- a/src/ImageSharp/Formats/ImageFormatManager.cs +++ b/src/ImageSharp/Formats/ImageFormatManager.cs @@ -1,201 +1,201 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Linq; - -namespace SixLabors.ImageSharp.Formats -{ - /// - /// Collection of Image Formats to be used in class. - /// - public class ImageFormatManager - { - /// - /// Used for locking against as there is no ConcurrentSet type. - /// - /// - private static readonly object HashLock = new object(); - - /// - /// The list of supported keyed to mime types. - /// - private readonly ConcurrentDictionary mimeTypeEncoders = new ConcurrentDictionary(); - - /// - /// The list of supported keyed to mime types. - /// - private readonly ConcurrentDictionary mimeTypeDecoders = new ConcurrentDictionary(); - - /// - /// The list of supported s. - /// - private readonly HashSet imageFormats = new HashSet(); - - /// - /// The list of supported s. - /// - private ConcurrentBag imageFormatDetectors = new ConcurrentBag(); - - /// - /// Initializes a new instance of the class. - /// - public ImageFormatManager() - { - } - - /// - /// Gets the maximum header size of all the formats. - /// - internal int MaxHeaderSize { get; private set; } - - /// - /// Gets the currently registered s. - /// - public IEnumerable ImageFormats => this.imageFormats; - - /// - /// Gets the currently registered s. - /// - internal IEnumerable FormatDetectors => this.imageFormatDetectors; - - /// - /// Gets the currently registered s. - /// - internal IEnumerable> ImageDecoders => this.mimeTypeDecoders; - - /// - /// Gets the currently registered s. - /// - internal IEnumerable> ImageEncoders => this.mimeTypeEncoders; - - /// - /// Registers a new format provider. - /// - /// The format to register as a known format. - public void AddImageFormat(IImageFormat format) - { - Guard.NotNull(format, nameof(format)); - Guard.NotNull(format.MimeTypes, nameof(format.MimeTypes)); - Guard.NotNull(format.FileExtensions, nameof(format.FileExtensions)); - - lock (HashLock) - { - if (!this.imageFormats.Contains(format)) - { - this.imageFormats.Add(format); - } - } - } - - /// - /// For the specified file extensions type find the e . - /// - /// The extension to discover - /// The if found otherwise null - public IImageFormat FindFormatByFileExtension(string extension) - { - Guard.NotNullOrWhiteSpace(extension, nameof(extension)); - - if (extension[0] == '.') - { - extension = extension.Substring(1); - } - - return this.imageFormats.FirstOrDefault(x => x.FileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase)); - } - - /// - /// For the specified mime type find the . - /// - /// The mime-type to discover - /// The if found; otherwise null - public IImageFormat FindFormatByMimeType(string mimeType) - { - return this.imageFormats.FirstOrDefault(x => x.MimeTypes.Contains(mimeType, StringComparer.OrdinalIgnoreCase)); - } - - /// - /// Sets a specific image encoder as the encoder for a specific image format. - /// - /// The image format to register the encoder for. - /// The encoder to use, - public void SetEncoder(IImageFormat imageFormat, IImageEncoder encoder) - { - Guard.NotNull(imageFormat, nameof(imageFormat)); - Guard.NotNull(encoder, nameof(encoder)); - this.AddImageFormat(imageFormat); - this.mimeTypeEncoders.AddOrUpdate(imageFormat, encoder, (s, e) => encoder); - } - - /// - /// Sets a specific image decoder as the decoder for a specific image format. - /// - /// The image format to register the encoder for. - /// The decoder to use, - public void SetDecoder(IImageFormat imageFormat, IImageDecoder decoder) - { - Guard.NotNull(imageFormat, nameof(imageFormat)); - Guard.NotNull(decoder, nameof(decoder)); - this.AddImageFormat(imageFormat); - this.mimeTypeDecoders.AddOrUpdate(imageFormat, decoder, (s, e) => decoder); - } - - /// - /// Removes all the registered image format detectors. - /// - public void ClearImageFormatDetectors() - { - this.imageFormatDetectors = new ConcurrentBag(); - } - - /// - /// Adds a new detector for detecting mime types. - /// - /// The detector to add - public void AddImageFormatDetector(IImageFormatDetector detector) - { - Guard.NotNull(detector, nameof(detector)); - this.imageFormatDetectors.Add(detector); - this.SetMaxHeaderSize(); - } - - /// - /// For the specified mime type find the decoder. - /// - /// The format to discover - /// The if found otherwise null - public IImageDecoder FindDecoder(IImageFormat format) - { - Guard.NotNull(format, nameof(format)); - - return this.mimeTypeDecoders.TryGetValue(format, out IImageDecoder decoder) - ? decoder - : null; - } - - /// - /// For the specified mime type find the encoder. - /// - /// The format to discover - /// The if found otherwise null - public IImageEncoder FindEncoder(IImageFormat format) - { - Guard.NotNull(format, nameof(format)); - - return this.mimeTypeEncoders.TryGetValue(format, out IImageEncoder encoder) - ? encoder - : null; - } - - /// - /// Sets the max header size. - /// - private void SetMaxHeaderSize() - { - this.MaxHeaderSize = this.imageFormatDetectors.Max(x => x.HeaderSize); - } - } -} +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; + +namespace SixLabors.ImageSharp.Formats +{ + /// + /// Collection of Image Formats to be used in class. + /// + public class ImageFormatManager + { + /// + /// Used for locking against as there is no ConcurrentSet type. + /// + /// + private static readonly object HashLock = new object(); + + /// + /// The list of supported keyed to mime types. + /// + private readonly ConcurrentDictionary mimeTypeEncoders = new ConcurrentDictionary(); + + /// + /// The list of supported keyed to mime types. + /// + private readonly ConcurrentDictionary mimeTypeDecoders = new ConcurrentDictionary(); + + /// + /// The list of supported s. + /// + private readonly HashSet imageFormats = new HashSet(); + + /// + /// The list of supported s. + /// + private ConcurrentBag imageFormatDetectors = new ConcurrentBag(); + + /// + /// Initializes a new instance of the class. + /// + public ImageFormatManager() + { + } + + /// + /// Gets the maximum header size of all the formats. + /// + internal int MaxHeaderSize { get; private set; } + + /// + /// Gets the currently registered s. + /// + public IEnumerable ImageFormats => this.imageFormats; + + /// + /// Gets the currently registered s. + /// + internal IEnumerable FormatDetectors => this.imageFormatDetectors; + + /// + /// Gets the currently registered s. + /// + internal IEnumerable> ImageDecoders => this.mimeTypeDecoders; + + /// + /// Gets the currently registered s. + /// + internal IEnumerable> ImageEncoders => this.mimeTypeEncoders; + + /// + /// Registers a new format provider. + /// + /// The format to register as a known format. + public void AddImageFormat(IImageFormat format) + { + Guard.NotNull(format, nameof(format)); + Guard.NotNull(format.MimeTypes, nameof(format.MimeTypes)); + Guard.NotNull(format.FileExtensions, nameof(format.FileExtensions)); + + lock (HashLock) + { + if (!this.imageFormats.Contains(format)) + { + this.imageFormats.Add(format); + } + } + } + + /// + /// For the specified file extensions type find the e . + /// + /// The extension to discover + /// The if found otherwise null + public IImageFormat FindFormatByFileExtension(string extension) + { + Guard.NotNullOrWhiteSpace(extension, nameof(extension)); + + if (extension[0] == '.') + { + extension = extension.Substring(1); + } + + return this.imageFormats.FirstOrDefault(x => x.FileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase)); + } + + /// + /// For the specified mime type find the . + /// + /// The mime-type to discover + /// The if found; otherwise null + public IImageFormat FindFormatByMimeType(string mimeType) + { + return this.imageFormats.FirstOrDefault(x => x.MimeTypes.Contains(mimeType, StringComparer.OrdinalIgnoreCase)); + } + + /// + /// Sets a specific image encoder as the encoder for a specific image format. + /// + /// The image format to register the encoder for. + /// The encoder to use, + public void SetEncoder(IImageFormat imageFormat, IImageEncoder encoder) + { + Guard.NotNull(imageFormat, nameof(imageFormat)); + Guard.NotNull(encoder, nameof(encoder)); + this.AddImageFormat(imageFormat); + this.mimeTypeEncoders.AddOrUpdate(imageFormat, encoder, (s, e) => encoder); + } + + /// + /// Sets a specific image decoder as the decoder for a specific image format. + /// + /// The image format to register the encoder for. + /// The decoder to use, + public void SetDecoder(IImageFormat imageFormat, IImageDecoder decoder) + { + Guard.NotNull(imageFormat, nameof(imageFormat)); + Guard.NotNull(decoder, nameof(decoder)); + this.AddImageFormat(imageFormat); + this.mimeTypeDecoders.AddOrUpdate(imageFormat, decoder, (s, e) => decoder); + } + + /// + /// Removes all the registered image format detectors. + /// + public void ClearImageFormatDetectors() + { + this.imageFormatDetectors = new ConcurrentBag(); + } + + /// + /// Adds a new detector for detecting mime types. + /// + /// The detector to add + public void AddImageFormatDetector(IImageFormatDetector detector) + { + Guard.NotNull(detector, nameof(detector)); + this.imageFormatDetectors.Add(detector); + this.SetMaxHeaderSize(); + } + + /// + /// For the specified mime type find the decoder. + /// + /// The format to discover + /// The if found otherwise null + public IImageDecoder FindDecoder(IImageFormat format) + { + Guard.NotNull(format, nameof(format)); + + return this.mimeTypeDecoders.TryGetValue(format, out IImageDecoder decoder) + ? decoder + : null; + } + + /// + /// For the specified mime type find the encoder. + /// + /// The format to discover + /// The if found otherwise null + public IImageEncoder FindEncoder(IImageFormat format) + { + Guard.NotNull(format, nameof(format)); + + return this.mimeTypeEncoders.TryGetValue(format, out IImageEncoder encoder) + ? encoder + : null; + } + + /// + /// Sets the max header size. + /// + private void SetMaxHeaderSize() + { + this.MaxHeaderSize = this.imageFormatDetectors.Max(x => x.HeaderSize); + } + } +} diff --git a/src/ImageSharp/Formats/Jpeg/5116.DCT_Filter.pdf b/src/ImageSharp/Formats/Jpeg/5116.DCT_Filter.pdf index 3423fb315..a5967a02e 100644 Binary files a/src/ImageSharp/Formats/Jpeg/5116.DCT_Filter.pdf and b/src/ImageSharp/Formats/Jpeg/5116.DCT_Filter.pdf differ diff --git a/src/ImageSharp/Formats/Jpeg/itu-t81.pdf b/src/ImageSharp/Formats/Jpeg/itu-t81.pdf index 83fba254b..1d57c76c2 100644 Binary files a/src/ImageSharp/Formats/Jpeg/itu-t81.pdf and b/src/ImageSharp/Formats/Jpeg/itu-t81.pdf differ diff --git a/src/ImageSharp/GraphicsOptions.cs b/src/ImageSharp/GraphicsOptions.cs index 4d5bf6d51..214b10810 100644 --- a/src/ImageSharp/GraphicsOptions.cs +++ b/src/ImageSharp/GraphicsOptions.cs @@ -1,177 +1,177 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.PixelFormats; - -namespace SixLabors.ImageSharp -{ - /// - /// Options for influencing the drawing functions. - /// - public struct GraphicsOptions - { - /// - /// Represents the default . - /// - public static readonly GraphicsOptions Default = new GraphicsOptions(true); - - private float? blendPercentage; - - private int? antialiasSubpixelDepth; - - private bool? antialias; - - private PixelColorBlendingMode colorBlendingMode; - - private PixelAlphaCompositionMode alphaCompositionMode; - - /// - /// Initializes a new instance of the struct. - /// - /// If set to true [enable antialiasing]. - public GraphicsOptions(bool enableAntialiasing) - { - this.colorBlendingMode = PixelColorBlendingMode.Normal; - this.alphaCompositionMode = PixelAlphaCompositionMode.SrcOver; - this.blendPercentage = 1; - this.antialiasSubpixelDepth = 16; - this.antialias = enableAntialiasing; - } - - /// - /// Initializes a new instance of the struct. - /// - /// If set to true [enable antialiasing]. - /// blending percentage to apply to the drawing operation - public GraphicsOptions(bool enableAntialiasing, float opacity) - { - Guard.MustBeBetweenOrEqualTo(opacity, 0, 1, nameof(opacity)); - - this.colorBlendingMode = PixelColorBlendingMode.Normal; - this.alphaCompositionMode = PixelAlphaCompositionMode.SrcOver; - this.blendPercentage = opacity; - this.antialiasSubpixelDepth = 16; - this.antialias = enableAntialiasing; - } - - /// - /// Initializes a new instance of the struct. - /// - /// If set to true [enable antialiasing]. - /// blending percentage to apply to the drawing operation - /// color blending mode to apply to the drawing operation - public GraphicsOptions(bool enableAntialiasing, PixelColorBlendingMode blending, float opacity) - { - Guard.MustBeBetweenOrEqualTo(opacity, 0, 1, nameof(opacity)); - - this.colorBlendingMode = blending; - this.alphaCompositionMode = PixelAlphaCompositionMode.SrcOver; - this.blendPercentage = opacity; - this.antialiasSubpixelDepth = 16; - this.antialias = enableAntialiasing; - } - - /// - /// Initializes a new instance of the struct. - /// - /// If set to true [enable antialiasing]. - /// blending percentage to apply to the drawing operation - /// color blending mode to apply to the drawing operation - /// alpha composition mode to apply to the drawing operation - public GraphicsOptions(bool enableAntialiasing, PixelColorBlendingMode blending, PixelAlphaCompositionMode composition, float opacity) - { - Guard.MustBeBetweenOrEqualTo(opacity, 0, 1, nameof(opacity)); - - this.colorBlendingMode = blending; - this.alphaCompositionMode = composition; - this.blendPercentage = opacity; - this.antialiasSubpixelDepth = 16; - this.antialias = enableAntialiasing; - } - - /// - /// Gets or sets a value indicating whether antialiasing should be applied. - /// - public bool Antialias - { - get => this.antialias ?? true; - set => this.antialias = value; - } - - /// - /// Gets or sets a value indicating the number of subpixels to use while rendering with antialiasing enabled. - /// - public int AntialiasSubpixelDepth - { - get => this.antialiasSubpixelDepth ?? 16; - set => this.antialiasSubpixelDepth = value; - } - - /// - /// Gets or sets a value indicating the blending percentage to apply to the drawing operation - /// - public float BlendPercentage - { - get => (this.blendPercentage ?? 1).Clamp(0, 1); - set => this.blendPercentage = value; - } - - // In the future we could expose a PixelBlender directly on here - // or some forms of PixelBlender factory for each pixel type. Will need - // some API thought post V1. - - /// - /// Gets or sets a value indicating the color blending mode to apply to the drawing operation - /// - public PixelColorBlendingMode ColorBlendingMode - { - get => this.colorBlendingMode; - set => this.colorBlendingMode = value; - } - - /// - /// Gets or sets a value indicating the alpha composition mode to apply to the drawing operation - /// - public PixelAlphaCompositionMode AlphaCompositionMode - { - get => this.alphaCompositionMode; - set => this.alphaCompositionMode = value; - } - - /// - /// Evaluates if a given SOURCE color can completely replace a BACKDROP color given the current blending and composition settings. - /// - /// the color - /// true if the color can be considered opaque - /// - /// Blending and composition is an expensive operation, in some cases, like - /// filling with a solid color, the blending can be avoided by a plain color replacement. - /// This method can be useful for such processors to select the fast path. - /// - internal bool IsOpaqueColorWithoutBlending(Color color) - { - if (this.ColorBlendingMode != PixelColorBlendingMode.Normal) - { - return false; - } - - if (this.AlphaCompositionMode != PixelAlphaCompositionMode.SrcOver && - this.AlphaCompositionMode != PixelAlphaCompositionMode.Src) - { - return false; - } - - if (this.BlendPercentage != 1f) - { - return false; - } - - if (color.ToVector4().W != 1f) - { - return false; - } - - return true; - } - } +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp +{ + /// + /// Options for influencing the drawing functions. + /// + public struct GraphicsOptions + { + /// + /// Represents the default . + /// + public static readonly GraphicsOptions Default = new GraphicsOptions(true); + + private float? blendPercentage; + + private int? antialiasSubpixelDepth; + + private bool? antialias; + + private PixelColorBlendingMode colorBlendingMode; + + private PixelAlphaCompositionMode alphaCompositionMode; + + /// + /// Initializes a new instance of the struct. + /// + /// If set to true [enable antialiasing]. + public GraphicsOptions(bool enableAntialiasing) + { + this.colorBlendingMode = PixelColorBlendingMode.Normal; + this.alphaCompositionMode = PixelAlphaCompositionMode.SrcOver; + this.blendPercentage = 1; + this.antialiasSubpixelDepth = 16; + this.antialias = enableAntialiasing; + } + + /// + /// Initializes a new instance of the struct. + /// + /// If set to true [enable antialiasing]. + /// blending percentage to apply to the drawing operation + public GraphicsOptions(bool enableAntialiasing, float opacity) + { + Guard.MustBeBetweenOrEqualTo(opacity, 0, 1, nameof(opacity)); + + this.colorBlendingMode = PixelColorBlendingMode.Normal; + this.alphaCompositionMode = PixelAlphaCompositionMode.SrcOver; + this.blendPercentage = opacity; + this.antialiasSubpixelDepth = 16; + this.antialias = enableAntialiasing; + } + + /// + /// Initializes a new instance of the struct. + /// + /// If set to true [enable antialiasing]. + /// blending percentage to apply to the drawing operation + /// color blending mode to apply to the drawing operation + public GraphicsOptions(bool enableAntialiasing, PixelColorBlendingMode blending, float opacity) + { + Guard.MustBeBetweenOrEqualTo(opacity, 0, 1, nameof(opacity)); + + this.colorBlendingMode = blending; + this.alphaCompositionMode = PixelAlphaCompositionMode.SrcOver; + this.blendPercentage = opacity; + this.antialiasSubpixelDepth = 16; + this.antialias = enableAntialiasing; + } + + /// + /// Initializes a new instance of the struct. + /// + /// If set to true [enable antialiasing]. + /// blending percentage to apply to the drawing operation + /// color blending mode to apply to the drawing operation + /// alpha composition mode to apply to the drawing operation + public GraphicsOptions(bool enableAntialiasing, PixelColorBlendingMode blending, PixelAlphaCompositionMode composition, float opacity) + { + Guard.MustBeBetweenOrEqualTo(opacity, 0, 1, nameof(opacity)); + + this.colorBlendingMode = blending; + this.alphaCompositionMode = composition; + this.blendPercentage = opacity; + this.antialiasSubpixelDepth = 16; + this.antialias = enableAntialiasing; + } + + /// + /// Gets or sets a value indicating whether antialiasing should be applied. + /// + public bool Antialias + { + get => this.antialias ?? true; + set => this.antialias = value; + } + + /// + /// Gets or sets a value indicating the number of subpixels to use while rendering with antialiasing enabled. + /// + public int AntialiasSubpixelDepth + { + get => this.antialiasSubpixelDepth ?? 16; + set => this.antialiasSubpixelDepth = value; + } + + /// + /// Gets or sets a value indicating the blending percentage to apply to the drawing operation + /// + public float BlendPercentage + { + get => (this.blendPercentage ?? 1).Clamp(0, 1); + set => this.blendPercentage = value; + } + + // In the future we could expose a PixelBlender directly on here + // or some forms of PixelBlender factory for each pixel type. Will need + // some API thought post V1. + + /// + /// Gets or sets a value indicating the color blending mode to apply to the drawing operation + /// + public PixelColorBlendingMode ColorBlendingMode + { + get => this.colorBlendingMode; + set => this.colorBlendingMode = value; + } + + /// + /// Gets or sets a value indicating the alpha composition mode to apply to the drawing operation + /// + public PixelAlphaCompositionMode AlphaCompositionMode + { + get => this.alphaCompositionMode; + set => this.alphaCompositionMode = value; + } + + /// + /// Evaluates if a given SOURCE color can completely replace a BACKDROP color given the current blending and composition settings. + /// + /// the color + /// true if the color can be considered opaque + /// + /// Blending and composition is an expensive operation, in some cases, like + /// filling with a solid color, the blending can be avoided by a plain color replacement. + /// This method can be useful for such processors to select the fast path. + /// + internal bool IsOpaqueColorWithoutBlending(Color color) + { + if (this.ColorBlendingMode != PixelColorBlendingMode.Normal) + { + return false; + } + + if (this.AlphaCompositionMode != PixelAlphaCompositionMode.SrcOver && + this.AlphaCompositionMode != PixelAlphaCompositionMode.Src) + { + return false; + } + + if (this.BlendPercentage != 1f) + { + return false; + } + + if (color.ToVector4().W != 1f) + { + return false; + } + + return true; + } + } } \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/PixelAlphaCompositionMode.cs b/src/ImageSharp/PixelFormats/PixelAlphaCompositionMode.cs index 2758a7480..0d182d3c2 100644 --- a/src/ImageSharp/PixelFormats/PixelAlphaCompositionMode.cs +++ b/src/ImageSharp/PixelFormats/PixelAlphaCompositionMode.cs @@ -7,12 +7,12 @@ namespace SixLabors.ImageSharp.PixelFormats /// Enumerates the various alpha composition modes. /// public enum PixelAlphaCompositionMode - { + { /// /// returns the destination over the source. /// - SrcOver = 0, - + SrcOver = 0, + /// /// returns the source colors. /// diff --git a/src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.cs b/src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.cs index 1d3cb53af..0cf8d6bbb 100644 --- a/src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.cs @@ -1,3810 +1,3810 @@ -// 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 SixLabors.Memory; - -namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders -{ - /// - /// Collection of Porter Duff alpha blending functions applying different composition models. - /// - /// - /// These functions are designed to be a general solution for all color cases, - /// that is, they take in account the alpha value of both the backdrop - /// and source, and there's no need to alpha-premultiply neither the backdrop - /// nor the source. - /// Note there are faster functions for when the backdrop color is known - /// to be opaque - /// - internal static class DefaultPixelBlenders - where TPixel : struct, IPixel - { - - internal class NormalSrc : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static NormalSrc Instance { get; } = new NormalSrc(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.NormalSrc(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.NormalSrc(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class MultiplySrc : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static MultiplySrc Instance { get; } = new MultiplySrc(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.MultiplySrc(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.MultiplySrc(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class AddSrc : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static AddSrc Instance { get; } = new AddSrc(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.AddSrc(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.AddSrc(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class SubtractSrc : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static SubtractSrc Instance { get; } = new SubtractSrc(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.SubtractSrc(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.SubtractSrc(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class ScreenSrc : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static ScreenSrc Instance { get; } = new ScreenSrc(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.ScreenSrc(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.ScreenSrc(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class DarkenSrc : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static DarkenSrc Instance { get; } = new DarkenSrc(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.DarkenSrc(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.DarkenSrc(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class LightenSrc : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static LightenSrc Instance { get; } = new LightenSrc(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.LightenSrc(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.LightenSrc(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class OverlaySrc : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static OverlaySrc Instance { get; } = new OverlaySrc(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.OverlaySrc(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.OverlaySrc(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class HardLightSrc : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static HardLightSrc Instance { get; } = new HardLightSrc(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.HardLightSrc(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.HardLightSrc(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class NormalSrcAtop : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static NormalSrcAtop Instance { get; } = new NormalSrcAtop(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.NormalSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.NormalSrcAtop(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class MultiplySrcAtop : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static MultiplySrcAtop Instance { get; } = new MultiplySrcAtop(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.MultiplySrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.MultiplySrcAtop(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class AddSrcAtop : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static AddSrcAtop Instance { get; } = new AddSrcAtop(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.AddSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.AddSrcAtop(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class SubtractSrcAtop : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static SubtractSrcAtop Instance { get; } = new SubtractSrcAtop(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.SubtractSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.SubtractSrcAtop(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class ScreenSrcAtop : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static ScreenSrcAtop Instance { get; } = new ScreenSrcAtop(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.ScreenSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.ScreenSrcAtop(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class DarkenSrcAtop : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static DarkenSrcAtop Instance { get; } = new DarkenSrcAtop(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.DarkenSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.DarkenSrcAtop(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class LightenSrcAtop : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static LightenSrcAtop Instance { get; } = new LightenSrcAtop(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.LightenSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.LightenSrcAtop(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class OverlaySrcAtop : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static OverlaySrcAtop Instance { get; } = new OverlaySrcAtop(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.OverlaySrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.OverlaySrcAtop(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class HardLightSrcAtop : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static HardLightSrcAtop Instance { get; } = new HardLightSrcAtop(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.HardLightSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.HardLightSrcAtop(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class NormalSrcOver : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static NormalSrcOver Instance { get; } = new NormalSrcOver(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.NormalSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.NormalSrcOver(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class MultiplySrcOver : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static MultiplySrcOver Instance { get; } = new MultiplySrcOver(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.MultiplySrcOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.MultiplySrcOver(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class AddSrcOver : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static AddSrcOver Instance { get; } = new AddSrcOver(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.AddSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.AddSrcOver(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class SubtractSrcOver : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static SubtractSrcOver Instance { get; } = new SubtractSrcOver(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.SubtractSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.SubtractSrcOver(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class ScreenSrcOver : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static ScreenSrcOver Instance { get; } = new ScreenSrcOver(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.ScreenSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.ScreenSrcOver(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class DarkenSrcOver : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static DarkenSrcOver Instance { get; } = new DarkenSrcOver(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.DarkenSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.DarkenSrcOver(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class LightenSrcOver : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static LightenSrcOver Instance { get; } = new LightenSrcOver(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.LightenSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.LightenSrcOver(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class OverlaySrcOver : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static OverlaySrcOver Instance { get; } = new OverlaySrcOver(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.OverlaySrcOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.OverlaySrcOver(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class HardLightSrcOver : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static HardLightSrcOver Instance { get; } = new HardLightSrcOver(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.HardLightSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.HardLightSrcOver(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class NormalSrcIn : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static NormalSrcIn Instance { get; } = new NormalSrcIn(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.NormalSrcIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.NormalSrcIn(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class MultiplySrcIn : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static MultiplySrcIn Instance { get; } = new MultiplySrcIn(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.MultiplySrcIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.MultiplySrcIn(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class AddSrcIn : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static AddSrcIn Instance { get; } = new AddSrcIn(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.AddSrcIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.AddSrcIn(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class SubtractSrcIn : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static SubtractSrcIn Instance { get; } = new SubtractSrcIn(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.SubtractSrcIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.SubtractSrcIn(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class ScreenSrcIn : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static ScreenSrcIn Instance { get; } = new ScreenSrcIn(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.ScreenSrcIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.ScreenSrcIn(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class DarkenSrcIn : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static DarkenSrcIn Instance { get; } = new DarkenSrcIn(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.DarkenSrcIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.DarkenSrcIn(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class LightenSrcIn : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static LightenSrcIn Instance { get; } = new LightenSrcIn(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.LightenSrcIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.LightenSrcIn(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class OverlaySrcIn : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static OverlaySrcIn Instance { get; } = new OverlaySrcIn(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.OverlaySrcIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.OverlaySrcIn(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class HardLightSrcIn : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static HardLightSrcIn Instance { get; } = new HardLightSrcIn(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.HardLightSrcIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.HardLightSrcIn(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class NormalSrcOut : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static NormalSrcOut Instance { get; } = new NormalSrcOut(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.NormalSrcOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.NormalSrcOut(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class MultiplySrcOut : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static MultiplySrcOut Instance { get; } = new MultiplySrcOut(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.MultiplySrcOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.MultiplySrcOut(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class AddSrcOut : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static AddSrcOut Instance { get; } = new AddSrcOut(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.AddSrcOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.AddSrcOut(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class SubtractSrcOut : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static SubtractSrcOut Instance { get; } = new SubtractSrcOut(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.SubtractSrcOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.SubtractSrcOut(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class ScreenSrcOut : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static ScreenSrcOut Instance { get; } = new ScreenSrcOut(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.ScreenSrcOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.ScreenSrcOut(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class DarkenSrcOut : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static DarkenSrcOut Instance { get; } = new DarkenSrcOut(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.DarkenSrcOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.DarkenSrcOut(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class LightenSrcOut : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static LightenSrcOut Instance { get; } = new LightenSrcOut(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.LightenSrcOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.LightenSrcOut(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class OverlaySrcOut : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static OverlaySrcOut Instance { get; } = new OverlaySrcOut(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.OverlaySrcOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.OverlaySrcOut(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class HardLightSrcOut : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static HardLightSrcOut Instance { get; } = new HardLightSrcOut(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.HardLightSrcOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.HardLightSrcOut(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class NormalDest : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static NormalDest Instance { get; } = new NormalDest(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.NormalDest(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.NormalDest(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class MultiplyDest : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static MultiplyDest Instance { get; } = new MultiplyDest(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.MultiplyDest(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.MultiplyDest(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class AddDest : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static AddDest Instance { get; } = new AddDest(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.AddDest(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.AddDest(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class SubtractDest : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static SubtractDest Instance { get; } = new SubtractDest(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.SubtractDest(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.SubtractDest(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class ScreenDest : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static ScreenDest Instance { get; } = new ScreenDest(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.ScreenDest(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.ScreenDest(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class DarkenDest : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static DarkenDest Instance { get; } = new DarkenDest(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.DarkenDest(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.DarkenDest(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class LightenDest : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static LightenDest Instance { get; } = new LightenDest(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.LightenDest(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.LightenDest(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class OverlayDest : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static OverlayDest Instance { get; } = new OverlayDest(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.OverlayDest(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.OverlayDest(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class HardLightDest : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static HardLightDest Instance { get; } = new HardLightDest(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.HardLightDest(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.HardLightDest(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class NormalDestAtop : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static NormalDestAtop Instance { get; } = new NormalDestAtop(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.NormalDestAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.NormalDestAtop(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class MultiplyDestAtop : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static MultiplyDestAtop Instance { get; } = new MultiplyDestAtop(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.MultiplyDestAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.MultiplyDestAtop(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class AddDestAtop : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static AddDestAtop Instance { get; } = new AddDestAtop(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.AddDestAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.AddDestAtop(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class SubtractDestAtop : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static SubtractDestAtop Instance { get; } = new SubtractDestAtop(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.SubtractDestAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.SubtractDestAtop(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class ScreenDestAtop : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static ScreenDestAtop Instance { get; } = new ScreenDestAtop(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.ScreenDestAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.ScreenDestAtop(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class DarkenDestAtop : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static DarkenDestAtop Instance { get; } = new DarkenDestAtop(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.DarkenDestAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.DarkenDestAtop(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class LightenDestAtop : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static LightenDestAtop Instance { get; } = new LightenDestAtop(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.LightenDestAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.LightenDestAtop(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class OverlayDestAtop : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static OverlayDestAtop Instance { get; } = new OverlayDestAtop(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.OverlayDestAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.OverlayDestAtop(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class HardLightDestAtop : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static HardLightDestAtop Instance { get; } = new HardLightDestAtop(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.HardLightDestAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.HardLightDestAtop(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class NormalDestOver : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static NormalDestOver Instance { get; } = new NormalDestOver(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.NormalDestOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.NormalDestOver(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class MultiplyDestOver : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static MultiplyDestOver Instance { get; } = new MultiplyDestOver(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.MultiplyDestOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.MultiplyDestOver(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class AddDestOver : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static AddDestOver Instance { get; } = new AddDestOver(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.AddDestOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.AddDestOver(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class SubtractDestOver : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static SubtractDestOver Instance { get; } = new SubtractDestOver(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.SubtractDestOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.SubtractDestOver(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class ScreenDestOver : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static ScreenDestOver Instance { get; } = new ScreenDestOver(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.ScreenDestOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.ScreenDestOver(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class DarkenDestOver : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static DarkenDestOver Instance { get; } = new DarkenDestOver(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.DarkenDestOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.DarkenDestOver(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class LightenDestOver : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static LightenDestOver Instance { get; } = new LightenDestOver(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.LightenDestOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.LightenDestOver(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class OverlayDestOver : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static OverlayDestOver Instance { get; } = new OverlayDestOver(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.OverlayDestOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.OverlayDestOver(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class HardLightDestOver : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static HardLightDestOver Instance { get; } = new HardLightDestOver(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.HardLightDestOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.HardLightDestOver(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class NormalDestIn : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static NormalDestIn Instance { get; } = new NormalDestIn(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.NormalDestIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.NormalDestIn(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class MultiplyDestIn : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static MultiplyDestIn Instance { get; } = new MultiplyDestIn(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.MultiplyDestIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.MultiplyDestIn(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class AddDestIn : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static AddDestIn Instance { get; } = new AddDestIn(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.AddDestIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.AddDestIn(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class SubtractDestIn : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static SubtractDestIn Instance { get; } = new SubtractDestIn(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.SubtractDestIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.SubtractDestIn(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class ScreenDestIn : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static ScreenDestIn Instance { get; } = new ScreenDestIn(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.ScreenDestIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.ScreenDestIn(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class DarkenDestIn : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static DarkenDestIn Instance { get; } = new DarkenDestIn(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.DarkenDestIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.DarkenDestIn(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class LightenDestIn : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static LightenDestIn Instance { get; } = new LightenDestIn(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.LightenDestIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.LightenDestIn(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class OverlayDestIn : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static OverlayDestIn Instance { get; } = new OverlayDestIn(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.OverlayDestIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.OverlayDestIn(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class HardLightDestIn : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static HardLightDestIn Instance { get; } = new HardLightDestIn(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.HardLightDestIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.HardLightDestIn(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class NormalDestOut : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static NormalDestOut Instance { get; } = new NormalDestOut(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.NormalDestOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.NormalDestOut(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class MultiplyDestOut : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static MultiplyDestOut Instance { get; } = new MultiplyDestOut(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.MultiplyDestOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.MultiplyDestOut(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class AddDestOut : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static AddDestOut Instance { get; } = new AddDestOut(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.AddDestOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.AddDestOut(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class SubtractDestOut : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static SubtractDestOut Instance { get; } = new SubtractDestOut(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.SubtractDestOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.SubtractDestOut(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class ScreenDestOut : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static ScreenDestOut Instance { get; } = new ScreenDestOut(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.ScreenDestOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.ScreenDestOut(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class DarkenDestOut : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static DarkenDestOut Instance { get; } = new DarkenDestOut(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.DarkenDestOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.DarkenDestOut(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class LightenDestOut : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static LightenDestOut Instance { get; } = new LightenDestOut(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.LightenDestOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.LightenDestOut(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class OverlayDestOut : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static OverlayDestOut Instance { get; } = new OverlayDestOut(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.OverlayDestOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.OverlayDestOut(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class HardLightDestOut : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static HardLightDestOut Instance { get; } = new HardLightDestOut(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.HardLightDestOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.HardLightDestOut(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class NormalClear : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static NormalClear Instance { get; } = new NormalClear(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.NormalClear(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.NormalClear(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class MultiplyClear : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static MultiplyClear Instance { get; } = new MultiplyClear(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.MultiplyClear(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.MultiplyClear(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class AddClear : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static AddClear Instance { get; } = new AddClear(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.AddClear(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.AddClear(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class SubtractClear : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static SubtractClear Instance { get; } = new SubtractClear(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.SubtractClear(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.SubtractClear(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class ScreenClear : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static ScreenClear Instance { get; } = new ScreenClear(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.ScreenClear(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.ScreenClear(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class DarkenClear : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static DarkenClear Instance { get; } = new DarkenClear(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.DarkenClear(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.DarkenClear(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class LightenClear : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static LightenClear Instance { get; } = new LightenClear(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.LightenClear(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.LightenClear(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class OverlayClear : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static OverlayClear Instance { get; } = new OverlayClear(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.OverlayClear(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.OverlayClear(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class HardLightClear : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static HardLightClear Instance { get; } = new HardLightClear(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.HardLightClear(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.HardLightClear(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class NormalXor : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static NormalXor Instance { get; } = new NormalXor(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.NormalXor(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.NormalXor(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class MultiplyXor : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static MultiplyXor Instance { get; } = new MultiplyXor(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.MultiplyXor(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.MultiplyXor(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class AddXor : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static AddXor Instance { get; } = new AddXor(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.AddXor(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.AddXor(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class SubtractXor : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static SubtractXor Instance { get; } = new SubtractXor(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.SubtractXor(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.SubtractXor(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class ScreenXor : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static ScreenXor Instance { get; } = new ScreenXor(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.ScreenXor(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.ScreenXor(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class DarkenXor : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static DarkenXor Instance { get; } = new DarkenXor(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.DarkenXor(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.DarkenXor(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class LightenXor : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static LightenXor Instance { get; } = new LightenXor(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.LightenXor(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.LightenXor(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class OverlayXor : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static OverlayXor Instance { get; } = new OverlayXor(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.OverlayXor(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.OverlayXor(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - internal class HardLightXor : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static HardLightXor Instance { get; } = new HardLightXor(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.HardLightXor(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.HardLightXor(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - - } +// 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 SixLabors.Memory; + +namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders +{ + /// + /// Collection of Porter Duff alpha blending functions applying different composition models. + /// + /// + /// These functions are designed to be a general solution for all color cases, + /// that is, they take in account the alpha value of both the backdrop + /// and source, and there's no need to alpha-premultiply neither the backdrop + /// nor the source. + /// Note there are faster functions for when the backdrop color is known + /// to be opaque + /// + internal static class DefaultPixelBlenders + where TPixel : struct, IPixel + { + + internal class NormalSrc : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static NormalSrc Instance { get; } = new NormalSrc(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.NormalSrc(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.NormalSrc(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class MultiplySrc : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static MultiplySrc Instance { get; } = new MultiplySrc(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.MultiplySrc(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.MultiplySrc(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class AddSrc : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static AddSrc Instance { get; } = new AddSrc(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.AddSrc(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.AddSrc(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class SubtractSrc : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static SubtractSrc Instance { get; } = new SubtractSrc(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.SubtractSrc(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.SubtractSrc(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class ScreenSrc : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static ScreenSrc Instance { get; } = new ScreenSrc(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.ScreenSrc(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.ScreenSrc(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class DarkenSrc : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static DarkenSrc Instance { get; } = new DarkenSrc(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.DarkenSrc(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.DarkenSrc(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class LightenSrc : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static LightenSrc Instance { get; } = new LightenSrc(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.LightenSrc(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.LightenSrc(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class OverlaySrc : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static OverlaySrc Instance { get; } = new OverlaySrc(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.OverlaySrc(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.OverlaySrc(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class HardLightSrc : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static HardLightSrc Instance { get; } = new HardLightSrc(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.HardLightSrc(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.HardLightSrc(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class NormalSrcAtop : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static NormalSrcAtop Instance { get; } = new NormalSrcAtop(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.NormalSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.NormalSrcAtop(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class MultiplySrcAtop : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static MultiplySrcAtop Instance { get; } = new MultiplySrcAtop(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.MultiplySrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.MultiplySrcAtop(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class AddSrcAtop : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static AddSrcAtop Instance { get; } = new AddSrcAtop(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.AddSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.AddSrcAtop(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class SubtractSrcAtop : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static SubtractSrcAtop Instance { get; } = new SubtractSrcAtop(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.SubtractSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.SubtractSrcAtop(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class ScreenSrcAtop : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static ScreenSrcAtop Instance { get; } = new ScreenSrcAtop(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.ScreenSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.ScreenSrcAtop(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class DarkenSrcAtop : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static DarkenSrcAtop Instance { get; } = new DarkenSrcAtop(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.DarkenSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.DarkenSrcAtop(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class LightenSrcAtop : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static LightenSrcAtop Instance { get; } = new LightenSrcAtop(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.LightenSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.LightenSrcAtop(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class OverlaySrcAtop : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static OverlaySrcAtop Instance { get; } = new OverlaySrcAtop(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.OverlaySrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.OverlaySrcAtop(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class HardLightSrcAtop : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static HardLightSrcAtop Instance { get; } = new HardLightSrcAtop(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.HardLightSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.HardLightSrcAtop(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class NormalSrcOver : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static NormalSrcOver Instance { get; } = new NormalSrcOver(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.NormalSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.NormalSrcOver(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class MultiplySrcOver : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static MultiplySrcOver Instance { get; } = new MultiplySrcOver(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.MultiplySrcOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.MultiplySrcOver(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class AddSrcOver : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static AddSrcOver Instance { get; } = new AddSrcOver(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.AddSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.AddSrcOver(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class SubtractSrcOver : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static SubtractSrcOver Instance { get; } = new SubtractSrcOver(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.SubtractSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.SubtractSrcOver(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class ScreenSrcOver : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static ScreenSrcOver Instance { get; } = new ScreenSrcOver(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.ScreenSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.ScreenSrcOver(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class DarkenSrcOver : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static DarkenSrcOver Instance { get; } = new DarkenSrcOver(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.DarkenSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.DarkenSrcOver(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class LightenSrcOver : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static LightenSrcOver Instance { get; } = new LightenSrcOver(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.LightenSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.LightenSrcOver(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class OverlaySrcOver : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static OverlaySrcOver Instance { get; } = new OverlaySrcOver(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.OverlaySrcOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.OverlaySrcOver(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class HardLightSrcOver : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static HardLightSrcOver Instance { get; } = new HardLightSrcOver(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.HardLightSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.HardLightSrcOver(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class NormalSrcIn : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static NormalSrcIn Instance { get; } = new NormalSrcIn(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.NormalSrcIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.NormalSrcIn(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class MultiplySrcIn : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static MultiplySrcIn Instance { get; } = new MultiplySrcIn(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.MultiplySrcIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.MultiplySrcIn(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class AddSrcIn : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static AddSrcIn Instance { get; } = new AddSrcIn(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.AddSrcIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.AddSrcIn(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class SubtractSrcIn : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static SubtractSrcIn Instance { get; } = new SubtractSrcIn(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.SubtractSrcIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.SubtractSrcIn(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class ScreenSrcIn : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static ScreenSrcIn Instance { get; } = new ScreenSrcIn(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.ScreenSrcIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.ScreenSrcIn(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class DarkenSrcIn : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static DarkenSrcIn Instance { get; } = new DarkenSrcIn(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.DarkenSrcIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.DarkenSrcIn(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class LightenSrcIn : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static LightenSrcIn Instance { get; } = new LightenSrcIn(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.LightenSrcIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.LightenSrcIn(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class OverlaySrcIn : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static OverlaySrcIn Instance { get; } = new OverlaySrcIn(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.OverlaySrcIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.OverlaySrcIn(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class HardLightSrcIn : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static HardLightSrcIn Instance { get; } = new HardLightSrcIn(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.HardLightSrcIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.HardLightSrcIn(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class NormalSrcOut : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static NormalSrcOut Instance { get; } = new NormalSrcOut(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.NormalSrcOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.NormalSrcOut(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class MultiplySrcOut : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static MultiplySrcOut Instance { get; } = new MultiplySrcOut(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.MultiplySrcOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.MultiplySrcOut(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class AddSrcOut : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static AddSrcOut Instance { get; } = new AddSrcOut(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.AddSrcOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.AddSrcOut(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class SubtractSrcOut : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static SubtractSrcOut Instance { get; } = new SubtractSrcOut(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.SubtractSrcOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.SubtractSrcOut(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class ScreenSrcOut : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static ScreenSrcOut Instance { get; } = new ScreenSrcOut(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.ScreenSrcOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.ScreenSrcOut(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class DarkenSrcOut : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static DarkenSrcOut Instance { get; } = new DarkenSrcOut(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.DarkenSrcOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.DarkenSrcOut(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class LightenSrcOut : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static LightenSrcOut Instance { get; } = new LightenSrcOut(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.LightenSrcOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.LightenSrcOut(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class OverlaySrcOut : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static OverlaySrcOut Instance { get; } = new OverlaySrcOut(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.OverlaySrcOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.OverlaySrcOut(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class HardLightSrcOut : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static HardLightSrcOut Instance { get; } = new HardLightSrcOut(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.HardLightSrcOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.HardLightSrcOut(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class NormalDest : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static NormalDest Instance { get; } = new NormalDest(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.NormalDest(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.NormalDest(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class MultiplyDest : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static MultiplyDest Instance { get; } = new MultiplyDest(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.MultiplyDest(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.MultiplyDest(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class AddDest : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static AddDest Instance { get; } = new AddDest(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.AddDest(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.AddDest(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class SubtractDest : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static SubtractDest Instance { get; } = new SubtractDest(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.SubtractDest(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.SubtractDest(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class ScreenDest : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static ScreenDest Instance { get; } = new ScreenDest(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.ScreenDest(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.ScreenDest(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class DarkenDest : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static DarkenDest Instance { get; } = new DarkenDest(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.DarkenDest(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.DarkenDest(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class LightenDest : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static LightenDest Instance { get; } = new LightenDest(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.LightenDest(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.LightenDest(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class OverlayDest : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static OverlayDest Instance { get; } = new OverlayDest(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.OverlayDest(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.OverlayDest(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class HardLightDest : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static HardLightDest Instance { get; } = new HardLightDest(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.HardLightDest(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.HardLightDest(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class NormalDestAtop : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static NormalDestAtop Instance { get; } = new NormalDestAtop(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.NormalDestAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.NormalDestAtop(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class MultiplyDestAtop : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static MultiplyDestAtop Instance { get; } = new MultiplyDestAtop(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.MultiplyDestAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.MultiplyDestAtop(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class AddDestAtop : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static AddDestAtop Instance { get; } = new AddDestAtop(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.AddDestAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.AddDestAtop(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class SubtractDestAtop : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static SubtractDestAtop Instance { get; } = new SubtractDestAtop(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.SubtractDestAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.SubtractDestAtop(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class ScreenDestAtop : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static ScreenDestAtop Instance { get; } = new ScreenDestAtop(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.ScreenDestAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.ScreenDestAtop(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class DarkenDestAtop : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static DarkenDestAtop Instance { get; } = new DarkenDestAtop(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.DarkenDestAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.DarkenDestAtop(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class LightenDestAtop : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static LightenDestAtop Instance { get; } = new LightenDestAtop(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.LightenDestAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.LightenDestAtop(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class OverlayDestAtop : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static OverlayDestAtop Instance { get; } = new OverlayDestAtop(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.OverlayDestAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.OverlayDestAtop(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class HardLightDestAtop : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static HardLightDestAtop Instance { get; } = new HardLightDestAtop(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.HardLightDestAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.HardLightDestAtop(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class NormalDestOver : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static NormalDestOver Instance { get; } = new NormalDestOver(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.NormalDestOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.NormalDestOver(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class MultiplyDestOver : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static MultiplyDestOver Instance { get; } = new MultiplyDestOver(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.MultiplyDestOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.MultiplyDestOver(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class AddDestOver : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static AddDestOver Instance { get; } = new AddDestOver(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.AddDestOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.AddDestOver(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class SubtractDestOver : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static SubtractDestOver Instance { get; } = new SubtractDestOver(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.SubtractDestOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.SubtractDestOver(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class ScreenDestOver : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static ScreenDestOver Instance { get; } = new ScreenDestOver(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.ScreenDestOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.ScreenDestOver(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class DarkenDestOver : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static DarkenDestOver Instance { get; } = new DarkenDestOver(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.DarkenDestOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.DarkenDestOver(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class LightenDestOver : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static LightenDestOver Instance { get; } = new LightenDestOver(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.LightenDestOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.LightenDestOver(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class OverlayDestOver : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static OverlayDestOver Instance { get; } = new OverlayDestOver(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.OverlayDestOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.OverlayDestOver(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class HardLightDestOver : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static HardLightDestOver Instance { get; } = new HardLightDestOver(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.HardLightDestOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.HardLightDestOver(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class NormalDestIn : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static NormalDestIn Instance { get; } = new NormalDestIn(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.NormalDestIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.NormalDestIn(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class MultiplyDestIn : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static MultiplyDestIn Instance { get; } = new MultiplyDestIn(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.MultiplyDestIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.MultiplyDestIn(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class AddDestIn : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static AddDestIn Instance { get; } = new AddDestIn(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.AddDestIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.AddDestIn(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class SubtractDestIn : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static SubtractDestIn Instance { get; } = new SubtractDestIn(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.SubtractDestIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.SubtractDestIn(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class ScreenDestIn : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static ScreenDestIn Instance { get; } = new ScreenDestIn(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.ScreenDestIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.ScreenDestIn(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class DarkenDestIn : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static DarkenDestIn Instance { get; } = new DarkenDestIn(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.DarkenDestIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.DarkenDestIn(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class LightenDestIn : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static LightenDestIn Instance { get; } = new LightenDestIn(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.LightenDestIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.LightenDestIn(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class OverlayDestIn : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static OverlayDestIn Instance { get; } = new OverlayDestIn(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.OverlayDestIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.OverlayDestIn(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class HardLightDestIn : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static HardLightDestIn Instance { get; } = new HardLightDestIn(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.HardLightDestIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.HardLightDestIn(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class NormalDestOut : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static NormalDestOut Instance { get; } = new NormalDestOut(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.NormalDestOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.NormalDestOut(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class MultiplyDestOut : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static MultiplyDestOut Instance { get; } = new MultiplyDestOut(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.MultiplyDestOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.MultiplyDestOut(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class AddDestOut : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static AddDestOut Instance { get; } = new AddDestOut(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.AddDestOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.AddDestOut(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class SubtractDestOut : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static SubtractDestOut Instance { get; } = new SubtractDestOut(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.SubtractDestOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.SubtractDestOut(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class ScreenDestOut : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static ScreenDestOut Instance { get; } = new ScreenDestOut(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.ScreenDestOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.ScreenDestOut(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class DarkenDestOut : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static DarkenDestOut Instance { get; } = new DarkenDestOut(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.DarkenDestOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.DarkenDestOut(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class LightenDestOut : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static LightenDestOut Instance { get; } = new LightenDestOut(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.LightenDestOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.LightenDestOut(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class OverlayDestOut : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static OverlayDestOut Instance { get; } = new OverlayDestOut(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.OverlayDestOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.OverlayDestOut(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class HardLightDestOut : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static HardLightDestOut Instance { get; } = new HardLightDestOut(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.HardLightDestOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.HardLightDestOut(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class NormalClear : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static NormalClear Instance { get; } = new NormalClear(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.NormalClear(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.NormalClear(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class MultiplyClear : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static MultiplyClear Instance { get; } = new MultiplyClear(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.MultiplyClear(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.MultiplyClear(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class AddClear : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static AddClear Instance { get; } = new AddClear(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.AddClear(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.AddClear(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class SubtractClear : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static SubtractClear Instance { get; } = new SubtractClear(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.SubtractClear(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.SubtractClear(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class ScreenClear : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static ScreenClear Instance { get; } = new ScreenClear(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.ScreenClear(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.ScreenClear(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class DarkenClear : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static DarkenClear Instance { get; } = new DarkenClear(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.DarkenClear(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.DarkenClear(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class LightenClear : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static LightenClear Instance { get; } = new LightenClear(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.LightenClear(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.LightenClear(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class OverlayClear : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static OverlayClear Instance { get; } = new OverlayClear(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.OverlayClear(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.OverlayClear(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class HardLightClear : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static HardLightClear Instance { get; } = new HardLightClear(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.HardLightClear(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.HardLightClear(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class NormalXor : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static NormalXor Instance { get; } = new NormalXor(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.NormalXor(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.NormalXor(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class MultiplyXor : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static MultiplyXor Instance { get; } = new MultiplyXor(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.MultiplyXor(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.MultiplyXor(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class AddXor : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static AddXor Instance { get; } = new AddXor(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.AddXor(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.AddXor(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class SubtractXor : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static SubtractXor Instance { get; } = new SubtractXor(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.SubtractXor(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.SubtractXor(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class ScreenXor : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static ScreenXor Instance { get; } = new ScreenXor(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.ScreenXor(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.ScreenXor(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class DarkenXor : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static DarkenXor Instance { get; } = new DarkenXor(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.DarkenXor(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.DarkenXor(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class LightenXor : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static LightenXor Instance { get; } = new LightenXor(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.LightenXor(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.LightenXor(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class OverlayXor : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static OverlayXor Instance { get; } = new OverlayXor(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.OverlayXor(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.OverlayXor(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + internal class HardLightXor : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static HardLightXor Instance { get; } = new HardLightXor(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.HardLightXor(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.HardLightXor(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + + } } \ 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 b7ea7a9d4..2cca55e4c 100644 --- a/src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.tt +++ b/src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.tt @@ -1,114 +1,114 @@ -<# -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. -#> -<#@ template debug="false" hostspecific="false" language="C#" #> -<#@ assembly name="System.Core" #> -<#@ import namespace="System.Linq" #> -<#@ import namespace="System.Text" #> -<#@ import namespace="System.Collections.Generic" #> -<#@ output extension=".cs" #> -// 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 SixLabors.Memory; - -namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders -{ - /// - /// Collection of Porter Duff alpha blending functions applying different composition models. - /// - /// - /// These functions are designed to be a general solution for all color cases, - /// that is, they take in account the alpha value of both the backdrop - /// and source, and there's no need to alpha-premultiply neither the backdrop - /// nor the source. - /// Note there are faster functions for when the backdrop color is known - /// to be opaque - /// - internal static class DefaultPixelBlenders - where TPixel : struct, IPixel - { - -<# - string[] composers = new []{ - "Src", - "SrcAtop", - "SrcOver", - "SrcIn", - "SrcOut", - "Dest", - "DestAtop", - "DestOver", - "DestIn", - "DestOut", - "Clear", - "Xor", - }; - - string[] blenders = new []{ - "Normal", - "Multiply", - "Add", - "Subtract", - "Screen", - "Darken", - "Lighten", - "Overlay", - "HardLight" - }; - - foreach(var composer in composers) { - foreach(var blender in blenders) { - - string blender_composer= $"{blender}{composer}"; - -#> - internal class <#= blender_composer#> : PixelBlender - { - /// - /// Gets the static instance of this blender. - /// - public static <#=blender_composer#> Instance { get; } = new <#=blender_composer#>(); - - /// - public override TPixel Blend(TPixel background, TPixel source, float amount) - { - TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.<#=blender_composer#>(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); - return dest; - } - - /// - protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) - { - amount = amount.Clamp(0, 1); - for (int i = 0; i < destination.Length; i++) - { - destination[i] = PorterDuffFunctions.<#=blender_composer#>(background[i], source[i], amount); - } - } - - /// - 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].Clamp(0, 1)); - } - } - } - -<# - } - } - -#> - } +<# +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. +#> +<#@ template debug="false" hostspecific="false" language="C#" #> +<#@ assembly name="System.Core" #> +<#@ import namespace="System.Linq" #> +<#@ import namespace="System.Text" #> +<#@ import namespace="System.Collections.Generic" #> +<#@ output extension=".cs" #> +// 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 SixLabors.Memory; + +namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders +{ + /// + /// Collection of Porter Duff alpha blending functions applying different composition models. + /// + /// + /// These functions are designed to be a general solution for all color cases, + /// that is, they take in account the alpha value of both the backdrop + /// and source, and there's no need to alpha-premultiply neither the backdrop + /// nor the source. + /// Note there are faster functions for when the backdrop color is known + /// to be opaque + /// + internal static class DefaultPixelBlenders + where TPixel : struct, IPixel + { + +<# + string[] composers = new []{ + "Src", + "SrcAtop", + "SrcOver", + "SrcIn", + "SrcOut", + "Dest", + "DestAtop", + "DestOver", + "DestIn", + "DestOut", + "Clear", + "Xor", + }; + + string[] blenders = new []{ + "Normal", + "Multiply", + "Add", + "Subtract", + "Screen", + "Darken", + "Lighten", + "Overlay", + "HardLight" + }; + + foreach(var composer in composers) { + foreach(var blender in blenders) { + + string blender_composer= $"{blender}{composer}"; + +#> + internal class <#= blender_composer#> : PixelBlender + { + /// + /// Gets the static instance of this blender. + /// + public static <#=blender_composer#> Instance { get; } = new <#=blender_composer#>(); + + /// + public override TPixel Blend(TPixel background, TPixel source, float amount) + { + TPixel dest = default; + dest.FromScaledVector4(PorterDuffFunctions.<#=blender_composer#>(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + return dest; + } + + /// + protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) + { + amount = amount.Clamp(0, 1); + for (int i = 0; i < destination.Length; i++) + { + destination[i] = PorterDuffFunctions.<#=blender_composer#>(background[i], source[i], amount); + } + } + + /// + 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].Clamp(0, 1)); + } + } + } + +<# + } + } + +#> + } } \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.cs b/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.cs index 64148746e..a99deb535 100644 --- a/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.cs @@ -1,2162 +1,2162 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -// - - -using System; -using System.Numerics; -using System.Runtime.CompilerServices; - -namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders -{ - internal static partial class PorterDuffFunctions - { - - - - - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 NormalSrc(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return source; - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 NormalSrcAtop(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Atop(backdrop, source, Normal(backdrop, source)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 NormalSrcOver(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Over(backdrop, source, Normal(backdrop, source)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 NormalSrcIn(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return In(backdrop, source, Normal(backdrop, source)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 NormalSrcOut(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Out(backdrop, source); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 NormalDest(Vector4 backdrop, Vector4 source, float opacity) - { - return backdrop; - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 NormalDestAtop(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Atop(source, backdrop, Normal(source, backdrop)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 NormalDestOver(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Over(source, backdrop, Normal(source, backdrop)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 NormalDestIn(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return In(source, backdrop, Normal(source, backdrop)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 NormalDestOut(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Out(source, backdrop); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 NormalXor(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Xor(backdrop, source); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 NormalClear(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Clear(backdrop, source); - } - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel NormalSrc(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(NormalSrc(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel NormalSrcAtop(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(NormalSrcAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel NormalSrcOver(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(NormalSrcOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel NormalSrcIn(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(NormalSrcIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel NormalSrcOut(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(NormalSrcOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel NormalDest(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(NormalDest(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel NormalDestAtop(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(NormalDestAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel NormalDestOver(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(NormalDestOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel NormalDestIn(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(NormalDestIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel NormalDestOut(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(NormalDestOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel NormalClear(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(NormalClear(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel NormalXor(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(NormalXor(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 MultiplySrc(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return source; - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 MultiplySrcAtop(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Atop(backdrop, source, Multiply(backdrop, source)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 MultiplySrcOver(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Over(backdrop, source, Multiply(backdrop, source)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 MultiplySrcIn(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return In(backdrop, source, Multiply(backdrop, source)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 MultiplySrcOut(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Out(backdrop, source); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 MultiplyDest(Vector4 backdrop, Vector4 source, float opacity) - { - return backdrop; - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 MultiplyDestAtop(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Atop(source, backdrop, Multiply(source, backdrop)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 MultiplyDestOver(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Over(source, backdrop, Multiply(source, backdrop)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 MultiplyDestIn(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return In(source, backdrop, Multiply(source, backdrop)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 MultiplyDestOut(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Out(source, backdrop); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 MultiplyXor(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Xor(backdrop, source); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 MultiplyClear(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Clear(backdrop, source); - } - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel MultiplySrc(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(MultiplySrc(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel MultiplySrcAtop(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(MultiplySrcAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel MultiplySrcOver(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(MultiplySrcOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel MultiplySrcIn(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(MultiplySrcIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel MultiplySrcOut(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(MultiplySrcOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel MultiplyDest(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(MultiplyDest(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel MultiplyDestAtop(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(MultiplyDestAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel MultiplyDestOver(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(MultiplyDestOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel MultiplyDestIn(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(MultiplyDestIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel MultiplyDestOut(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(MultiplyDestOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel MultiplyClear(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(MultiplyClear(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel MultiplyXor(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(MultiplyXor(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 AddSrc(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return source; - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 AddSrcAtop(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Atop(backdrop, source, Add(backdrop, source)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 AddSrcOver(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Over(backdrop, source, Add(backdrop, source)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 AddSrcIn(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return In(backdrop, source, Add(backdrop, source)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 AddSrcOut(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Out(backdrop, source); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 AddDest(Vector4 backdrop, Vector4 source, float opacity) - { - return backdrop; - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 AddDestAtop(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Atop(source, backdrop, Add(source, backdrop)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 AddDestOver(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Over(source, backdrop, Add(source, backdrop)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 AddDestIn(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return In(source, backdrop, Add(source, backdrop)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 AddDestOut(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Out(source, backdrop); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 AddXor(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Xor(backdrop, source); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 AddClear(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Clear(backdrop, source); - } - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel AddSrc(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(AddSrc(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel AddSrcAtop(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(AddSrcAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel AddSrcOver(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(AddSrcOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel AddSrcIn(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(AddSrcIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel AddSrcOut(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(AddSrcOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel AddDest(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(AddDest(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel AddDestAtop(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(AddDestAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel AddDestOver(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(AddDestOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel AddDestIn(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(AddDestIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel AddDestOut(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(AddDestOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel AddClear(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(AddClear(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel AddXor(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(AddXor(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 SubtractSrc(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return source; - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 SubtractSrcAtop(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Atop(backdrop, source, Subtract(backdrop, source)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 SubtractSrcOver(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Over(backdrop, source, Subtract(backdrop, source)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 SubtractSrcIn(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return In(backdrop, source, Subtract(backdrop, source)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 SubtractSrcOut(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Out(backdrop, source); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 SubtractDest(Vector4 backdrop, Vector4 source, float opacity) - { - return backdrop; - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 SubtractDestAtop(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Atop(source, backdrop, Subtract(source, backdrop)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 SubtractDestOver(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Over(source, backdrop, Subtract(source, backdrop)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 SubtractDestIn(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return In(source, backdrop, Subtract(source, backdrop)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 SubtractDestOut(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Out(source, backdrop); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 SubtractXor(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Xor(backdrop, source); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 SubtractClear(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Clear(backdrop, source); - } - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel SubtractSrc(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(SubtractSrc(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel SubtractSrcAtop(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(SubtractSrcAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel SubtractSrcOver(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(SubtractSrcOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel SubtractSrcIn(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(SubtractSrcIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel SubtractSrcOut(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(SubtractSrcOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel SubtractDest(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(SubtractDest(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel SubtractDestAtop(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(SubtractDestAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel SubtractDestOver(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(SubtractDestOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel SubtractDestIn(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(SubtractDestIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel SubtractDestOut(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(SubtractDestOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel SubtractClear(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(SubtractClear(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel SubtractXor(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(SubtractXor(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 ScreenSrc(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return source; - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 ScreenSrcAtop(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Atop(backdrop, source, Screen(backdrop, source)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 ScreenSrcOver(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Over(backdrop, source, Screen(backdrop, source)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 ScreenSrcIn(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return In(backdrop, source, Screen(backdrop, source)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 ScreenSrcOut(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Out(backdrop, source); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 ScreenDest(Vector4 backdrop, Vector4 source, float opacity) - { - return backdrop; - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 ScreenDestAtop(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Atop(source, backdrop, Screen(source, backdrop)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 ScreenDestOver(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Over(source, backdrop, Screen(source, backdrop)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 ScreenDestIn(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return In(source, backdrop, Screen(source, backdrop)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 ScreenDestOut(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Out(source, backdrop); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 ScreenXor(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Xor(backdrop, source); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 ScreenClear(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Clear(backdrop, source); - } - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel ScreenSrc(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(ScreenSrc(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel ScreenSrcAtop(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(ScreenSrcAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel ScreenSrcOver(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(ScreenSrcOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel ScreenSrcIn(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(ScreenSrcIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel ScreenSrcOut(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(ScreenSrcOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel ScreenDest(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(ScreenDest(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel ScreenDestAtop(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(ScreenDestAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel ScreenDestOver(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(ScreenDestOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel ScreenDestIn(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(ScreenDestIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel ScreenDestOut(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(ScreenDestOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel ScreenClear(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(ScreenClear(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel ScreenXor(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(ScreenXor(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 DarkenSrc(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return source; - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 DarkenSrcAtop(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Atop(backdrop, source, Darken(backdrop, source)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 DarkenSrcOver(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Over(backdrop, source, Darken(backdrop, source)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 DarkenSrcIn(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return In(backdrop, source, Darken(backdrop, source)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 DarkenSrcOut(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Out(backdrop, source); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 DarkenDest(Vector4 backdrop, Vector4 source, float opacity) - { - return backdrop; - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 DarkenDestAtop(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Atop(source, backdrop, Darken(source, backdrop)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 DarkenDestOver(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Over(source, backdrop, Darken(source, backdrop)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 DarkenDestIn(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return In(source, backdrop, Darken(source, backdrop)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 DarkenDestOut(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Out(source, backdrop); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 DarkenXor(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Xor(backdrop, source); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 DarkenClear(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Clear(backdrop, source); - } - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel DarkenSrc(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(DarkenSrc(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel DarkenSrcAtop(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(DarkenSrcAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel DarkenSrcOver(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(DarkenSrcOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel DarkenSrcIn(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(DarkenSrcIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel DarkenSrcOut(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(DarkenSrcOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel DarkenDest(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(DarkenDest(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel DarkenDestAtop(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(DarkenDestAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel DarkenDestOver(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(DarkenDestOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel DarkenDestIn(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(DarkenDestIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel DarkenDestOut(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(DarkenDestOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel DarkenClear(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(DarkenClear(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel DarkenXor(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(DarkenXor(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 LightenSrc(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return source; - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 LightenSrcAtop(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Atop(backdrop, source, Lighten(backdrop, source)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 LightenSrcOver(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Over(backdrop, source, Lighten(backdrop, source)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 LightenSrcIn(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return In(backdrop, source, Lighten(backdrop, source)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 LightenSrcOut(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Out(backdrop, source); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 LightenDest(Vector4 backdrop, Vector4 source, float opacity) - { - return backdrop; - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 LightenDestAtop(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Atop(source, backdrop, Lighten(source, backdrop)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 LightenDestOver(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Over(source, backdrop, Lighten(source, backdrop)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 LightenDestIn(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return In(source, backdrop, Lighten(source, backdrop)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 LightenDestOut(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Out(source, backdrop); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 LightenXor(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Xor(backdrop, source); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 LightenClear(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Clear(backdrop, source); - } - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel LightenSrc(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(LightenSrc(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel LightenSrcAtop(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(LightenSrcAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel LightenSrcOver(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(LightenSrcOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel LightenSrcIn(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(LightenSrcIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel LightenSrcOut(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(LightenSrcOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel LightenDest(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(LightenDest(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel LightenDestAtop(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(LightenDestAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel LightenDestOver(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(LightenDestOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel LightenDestIn(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(LightenDestIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel LightenDestOut(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(LightenDestOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel LightenClear(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(LightenClear(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel LightenXor(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(LightenXor(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 OverlaySrc(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return source; - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 OverlaySrcAtop(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Atop(backdrop, source, Overlay(backdrop, source)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 OverlaySrcOver(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Over(backdrop, source, Overlay(backdrop, source)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 OverlaySrcIn(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return In(backdrop, source, Overlay(backdrop, source)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 OverlaySrcOut(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Out(backdrop, source); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 OverlayDest(Vector4 backdrop, Vector4 source, float opacity) - { - return backdrop; - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 OverlayDestAtop(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Atop(source, backdrop, Overlay(source, backdrop)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 OverlayDestOver(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Over(source, backdrop, Overlay(source, backdrop)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 OverlayDestIn(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return In(source, backdrop, Overlay(source, backdrop)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 OverlayDestOut(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Out(source, backdrop); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 OverlayXor(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Xor(backdrop, source); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 OverlayClear(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Clear(backdrop, source); - } - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel OverlaySrc(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(OverlaySrc(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel OverlaySrcAtop(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(OverlaySrcAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel OverlaySrcOver(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(OverlaySrcOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel OverlaySrcIn(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(OverlaySrcIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel OverlaySrcOut(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(OverlaySrcOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel OverlayDest(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(OverlayDest(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel OverlayDestAtop(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(OverlayDestAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel OverlayDestOver(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(OverlayDestOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel OverlayDestIn(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(OverlayDestIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel OverlayDestOut(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(OverlayDestOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel OverlayClear(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(OverlayClear(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel OverlayXor(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(OverlayXor(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 HardLightSrc(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return source; - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 HardLightSrcAtop(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Atop(backdrop, source, HardLight(backdrop, source)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 HardLightSrcOver(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Over(backdrop, source, HardLight(backdrop, source)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 HardLightSrcIn(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return In(backdrop, source, HardLight(backdrop, source)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 HardLightSrcOut(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Out(backdrop, source); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 HardLightDest(Vector4 backdrop, Vector4 source, float opacity) - { - return backdrop; - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 HardLightDestAtop(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Atop(source, backdrop, HardLight(source, backdrop)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 HardLightDestOver(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Over(source, backdrop, HardLight(source, backdrop)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 HardLightDestIn(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return In(source, backdrop, HardLight(source, backdrop)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 HardLightDestOut(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Out(source, backdrop); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 HardLightXor(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Xor(backdrop, source); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 HardLightClear(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Clear(backdrop, source); - } - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel HardLightSrc(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(HardLightSrc(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel HardLightSrcAtop(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(HardLightSrcAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel HardLightSrcOver(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(HardLightSrcOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel HardLightSrcIn(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(HardLightSrcIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel HardLightSrcOut(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(HardLightSrcOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel HardLightDest(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(HardLightDest(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel HardLightDestAtop(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(HardLightDestAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel HardLightDestOver(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(HardLightDestOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel HardLightDestIn(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(HardLightDestIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel HardLightDestOut(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(HardLightDestOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel HardLightClear(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(HardLightClear(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel HardLightXor(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(HardLightXor(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - - } +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +// + + +using System; +using System.Numerics; +using System.Runtime.CompilerServices; + +namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders +{ + internal static partial class PorterDuffFunctions + { + + + + + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 NormalSrc(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return source; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 NormalSrcAtop(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Atop(backdrop, source, Normal(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 NormalSrcOver(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Over(backdrop, source, Normal(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 NormalSrcIn(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return In(backdrop, source, Normal(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 NormalSrcOut(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Out(backdrop, source); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 NormalDest(Vector4 backdrop, Vector4 source, float opacity) + { + return backdrop; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 NormalDestAtop(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Atop(source, backdrop, Normal(source, backdrop)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 NormalDestOver(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Over(source, backdrop, Normal(source, backdrop)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 NormalDestIn(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return In(source, backdrop, Normal(source, backdrop)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 NormalDestOut(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Out(source, backdrop); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 NormalXor(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Xor(backdrop, source); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 NormalClear(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Clear(backdrop, source); + } + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel NormalSrc(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(NormalSrc(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel NormalSrcAtop(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(NormalSrcAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel NormalSrcOver(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(NormalSrcOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel NormalSrcIn(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(NormalSrcIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel NormalSrcOut(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(NormalSrcOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel NormalDest(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(NormalDest(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel NormalDestAtop(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(NormalDestAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel NormalDestOver(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(NormalDestOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel NormalDestIn(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(NormalDestIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel NormalDestOut(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(NormalDestOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel NormalClear(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(NormalClear(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel NormalXor(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(NormalXor(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 MultiplySrc(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return source; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 MultiplySrcAtop(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Atop(backdrop, source, Multiply(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 MultiplySrcOver(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Over(backdrop, source, Multiply(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 MultiplySrcIn(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return In(backdrop, source, Multiply(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 MultiplySrcOut(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Out(backdrop, source); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 MultiplyDest(Vector4 backdrop, Vector4 source, float opacity) + { + return backdrop; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 MultiplyDestAtop(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Atop(source, backdrop, Multiply(source, backdrop)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 MultiplyDestOver(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Over(source, backdrop, Multiply(source, backdrop)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 MultiplyDestIn(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return In(source, backdrop, Multiply(source, backdrop)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 MultiplyDestOut(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Out(source, backdrop); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 MultiplyXor(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Xor(backdrop, source); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 MultiplyClear(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Clear(backdrop, source); + } + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel MultiplySrc(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(MultiplySrc(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel MultiplySrcAtop(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(MultiplySrcAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel MultiplySrcOver(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(MultiplySrcOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel MultiplySrcIn(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(MultiplySrcIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel MultiplySrcOut(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(MultiplySrcOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel MultiplyDest(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(MultiplyDest(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel MultiplyDestAtop(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(MultiplyDestAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel MultiplyDestOver(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(MultiplyDestOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel MultiplyDestIn(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(MultiplyDestIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel MultiplyDestOut(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(MultiplyDestOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel MultiplyClear(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(MultiplyClear(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel MultiplyXor(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(MultiplyXor(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 AddSrc(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return source; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 AddSrcAtop(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Atop(backdrop, source, Add(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 AddSrcOver(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Over(backdrop, source, Add(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 AddSrcIn(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return In(backdrop, source, Add(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 AddSrcOut(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Out(backdrop, source); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 AddDest(Vector4 backdrop, Vector4 source, float opacity) + { + return backdrop; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 AddDestAtop(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Atop(source, backdrop, Add(source, backdrop)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 AddDestOver(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Over(source, backdrop, Add(source, backdrop)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 AddDestIn(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return In(source, backdrop, Add(source, backdrop)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 AddDestOut(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Out(source, backdrop); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 AddXor(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Xor(backdrop, source); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 AddClear(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Clear(backdrop, source); + } + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel AddSrc(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(AddSrc(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel AddSrcAtop(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(AddSrcAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel AddSrcOver(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(AddSrcOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel AddSrcIn(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(AddSrcIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel AddSrcOut(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(AddSrcOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel AddDest(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(AddDest(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel AddDestAtop(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(AddDestAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel AddDestOver(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(AddDestOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel AddDestIn(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(AddDestIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel AddDestOut(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(AddDestOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel AddClear(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(AddClear(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel AddXor(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(AddXor(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 SubtractSrc(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return source; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 SubtractSrcAtop(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Atop(backdrop, source, Subtract(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 SubtractSrcOver(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Over(backdrop, source, Subtract(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 SubtractSrcIn(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return In(backdrop, source, Subtract(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 SubtractSrcOut(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Out(backdrop, source); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 SubtractDest(Vector4 backdrop, Vector4 source, float opacity) + { + return backdrop; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 SubtractDestAtop(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Atop(source, backdrop, Subtract(source, backdrop)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 SubtractDestOver(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Over(source, backdrop, Subtract(source, backdrop)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 SubtractDestIn(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return In(source, backdrop, Subtract(source, backdrop)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 SubtractDestOut(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Out(source, backdrop); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 SubtractXor(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Xor(backdrop, source); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 SubtractClear(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Clear(backdrop, source); + } + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel SubtractSrc(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(SubtractSrc(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel SubtractSrcAtop(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(SubtractSrcAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel SubtractSrcOver(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(SubtractSrcOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel SubtractSrcIn(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(SubtractSrcIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel SubtractSrcOut(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(SubtractSrcOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel SubtractDest(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(SubtractDest(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel SubtractDestAtop(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(SubtractDestAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel SubtractDestOver(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(SubtractDestOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel SubtractDestIn(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(SubtractDestIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel SubtractDestOut(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(SubtractDestOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel SubtractClear(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(SubtractClear(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel SubtractXor(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(SubtractXor(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 ScreenSrc(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return source; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 ScreenSrcAtop(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Atop(backdrop, source, Screen(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 ScreenSrcOver(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Over(backdrop, source, Screen(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 ScreenSrcIn(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return In(backdrop, source, Screen(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 ScreenSrcOut(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Out(backdrop, source); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 ScreenDest(Vector4 backdrop, Vector4 source, float opacity) + { + return backdrop; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 ScreenDestAtop(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Atop(source, backdrop, Screen(source, backdrop)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 ScreenDestOver(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Over(source, backdrop, Screen(source, backdrop)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 ScreenDestIn(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return In(source, backdrop, Screen(source, backdrop)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 ScreenDestOut(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Out(source, backdrop); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 ScreenXor(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Xor(backdrop, source); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 ScreenClear(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Clear(backdrop, source); + } + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel ScreenSrc(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(ScreenSrc(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel ScreenSrcAtop(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(ScreenSrcAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel ScreenSrcOver(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(ScreenSrcOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel ScreenSrcIn(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(ScreenSrcIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel ScreenSrcOut(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(ScreenSrcOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel ScreenDest(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(ScreenDest(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel ScreenDestAtop(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(ScreenDestAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel ScreenDestOver(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(ScreenDestOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel ScreenDestIn(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(ScreenDestIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel ScreenDestOut(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(ScreenDestOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel ScreenClear(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(ScreenClear(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel ScreenXor(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(ScreenXor(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 DarkenSrc(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return source; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 DarkenSrcAtop(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Atop(backdrop, source, Darken(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 DarkenSrcOver(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Over(backdrop, source, Darken(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 DarkenSrcIn(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return In(backdrop, source, Darken(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 DarkenSrcOut(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Out(backdrop, source); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 DarkenDest(Vector4 backdrop, Vector4 source, float opacity) + { + return backdrop; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 DarkenDestAtop(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Atop(source, backdrop, Darken(source, backdrop)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 DarkenDestOver(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Over(source, backdrop, Darken(source, backdrop)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 DarkenDestIn(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return In(source, backdrop, Darken(source, backdrop)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 DarkenDestOut(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Out(source, backdrop); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 DarkenXor(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Xor(backdrop, source); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 DarkenClear(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Clear(backdrop, source); + } + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel DarkenSrc(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(DarkenSrc(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel DarkenSrcAtop(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(DarkenSrcAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel DarkenSrcOver(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(DarkenSrcOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel DarkenSrcIn(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(DarkenSrcIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel DarkenSrcOut(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(DarkenSrcOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel DarkenDest(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(DarkenDest(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel DarkenDestAtop(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(DarkenDestAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel DarkenDestOver(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(DarkenDestOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel DarkenDestIn(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(DarkenDestIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel DarkenDestOut(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(DarkenDestOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel DarkenClear(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(DarkenClear(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel DarkenXor(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(DarkenXor(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 LightenSrc(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return source; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 LightenSrcAtop(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Atop(backdrop, source, Lighten(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 LightenSrcOver(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Over(backdrop, source, Lighten(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 LightenSrcIn(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return In(backdrop, source, Lighten(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 LightenSrcOut(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Out(backdrop, source); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 LightenDest(Vector4 backdrop, Vector4 source, float opacity) + { + return backdrop; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 LightenDestAtop(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Atop(source, backdrop, Lighten(source, backdrop)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 LightenDestOver(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Over(source, backdrop, Lighten(source, backdrop)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 LightenDestIn(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return In(source, backdrop, Lighten(source, backdrop)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 LightenDestOut(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Out(source, backdrop); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 LightenXor(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Xor(backdrop, source); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 LightenClear(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Clear(backdrop, source); + } + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel LightenSrc(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(LightenSrc(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel LightenSrcAtop(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(LightenSrcAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel LightenSrcOver(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(LightenSrcOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel LightenSrcIn(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(LightenSrcIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel LightenSrcOut(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(LightenSrcOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel LightenDest(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(LightenDest(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel LightenDestAtop(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(LightenDestAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel LightenDestOver(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(LightenDestOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel LightenDestIn(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(LightenDestIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel LightenDestOut(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(LightenDestOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel LightenClear(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(LightenClear(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel LightenXor(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(LightenXor(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 OverlaySrc(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return source; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 OverlaySrcAtop(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Atop(backdrop, source, Overlay(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 OverlaySrcOver(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Over(backdrop, source, Overlay(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 OverlaySrcIn(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return In(backdrop, source, Overlay(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 OverlaySrcOut(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Out(backdrop, source); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 OverlayDest(Vector4 backdrop, Vector4 source, float opacity) + { + return backdrop; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 OverlayDestAtop(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Atop(source, backdrop, Overlay(source, backdrop)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 OverlayDestOver(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Over(source, backdrop, Overlay(source, backdrop)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 OverlayDestIn(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return In(source, backdrop, Overlay(source, backdrop)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 OverlayDestOut(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Out(source, backdrop); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 OverlayXor(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Xor(backdrop, source); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 OverlayClear(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Clear(backdrop, source); + } + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel OverlaySrc(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(OverlaySrc(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel OverlaySrcAtop(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(OverlaySrcAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel OverlaySrcOver(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(OverlaySrcOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel OverlaySrcIn(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(OverlaySrcIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel OverlaySrcOut(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(OverlaySrcOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel OverlayDest(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(OverlayDest(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel OverlayDestAtop(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(OverlayDestAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel OverlayDestOver(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(OverlayDestOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel OverlayDestIn(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(OverlayDestIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel OverlayDestOut(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(OverlayDestOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel OverlayClear(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(OverlayClear(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel OverlayXor(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(OverlayXor(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 HardLightSrc(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return source; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 HardLightSrcAtop(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Atop(backdrop, source, HardLight(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 HardLightSrcOver(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Over(backdrop, source, HardLight(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 HardLightSrcIn(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return In(backdrop, source, HardLight(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 HardLightSrcOut(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Out(backdrop, source); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 HardLightDest(Vector4 backdrop, Vector4 source, float opacity) + { + return backdrop; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 HardLightDestAtop(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Atop(source, backdrop, HardLight(source, backdrop)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 HardLightDestOver(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Over(source, backdrop, HardLight(source, backdrop)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 HardLightDestIn(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return In(source, backdrop, HardLight(source, backdrop)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 HardLightDestOut(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Out(source, backdrop); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 HardLightXor(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Xor(backdrop, source); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 HardLightClear(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Clear(backdrop, source); + } + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel HardLightSrc(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(HardLightSrc(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel HardLightSrcAtop(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(HardLightSrcAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel HardLightSrcOver(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(HardLightSrcOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel HardLightSrcIn(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(HardLightSrcIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel HardLightSrcOut(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(HardLightSrcOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel HardLightDest(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(HardLightDest(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel HardLightDestAtop(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(HardLightDestAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel HardLightDestOver(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(HardLightDestOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel HardLightDestIn(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(HardLightDestIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel HardLightDestOut(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(HardLightDestOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel HardLightClear(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(HardLightClear(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel HardLightXor(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(HardLightXor(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + + } } \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.tt b/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.tt index e21a78031..c8345cfb9 100644 --- a/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.tt +++ b/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.tt @@ -1,183 +1,183 @@ -<# -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. -#> -<#@ template debug="false" hostspecific="false" language="C#" #> -<#@ assembly name="System.Core" #> -<#@ import namespace="System.Linq" #> -<#@ import namespace="System.Text" #> -<#@ import namespace="System.Collections.Generic" #> -<#@ output extension=".cs" #> -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -// - -<# -// Note use of MethodImplOptions.NoInlining. We have tests that are failing on certain architectures when -// AggresiveInlining is used. Confirmed on Intel i7-6600U in 64bit. -#> - -using System; -using System.Numerics; -using System.Runtime.CompilerServices; - -namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders -{ - internal static partial class PorterDuffFunctions - { - -<# void GeneratePixelBlenders(string blender) { #> - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 <#=blender#>Src(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return source; - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 <#=blender#>SrcAtop(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Atop(backdrop, source, <#=blender#>(backdrop, source)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 <#=blender#>SrcOver(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Over(backdrop, source, <#=blender#>(backdrop, source)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 <#=blender#>SrcIn(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return In(backdrop, source, <#=blender#>(backdrop, source)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 <#=blender#>SrcOut(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Out(backdrop, source); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 <#=blender#>Dest(Vector4 backdrop, Vector4 source, float opacity) - { - return backdrop; - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 <#=blender#>DestAtop(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Atop(source, backdrop, <#=blender#>(source, backdrop)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 <#=blender#>DestOver(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Over(source, backdrop, <#=blender#>(source, backdrop)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 <#=blender#>DestIn(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return In(source, backdrop, <#=blender#>(source, backdrop)); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 <#=blender#>DestOut(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Out(source, backdrop); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 <#=blender#>Xor(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Xor(backdrop, source); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static Vector4 <#=blender#>Clear(Vector4 backdrop, Vector4 source, float opacity) - { - source.W *= opacity; - - return Clear(backdrop, source); - } -<# } #> - - -<# void GenerateGenericPixelBlender(string blender, string composer) { #> - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TPixel <#=blender#><#=composer#>(TPixel backdrop, TPixel source, float opacity) - where TPixel : struct, IPixel - { - opacity = opacity.Clamp(0, 1); - TPixel dest = default; - dest.FromScaledVector4(<#=blender#><#=composer#>(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); - return dest; - } - -<# } #> - -<# - -string[] composers = new []{ - "Src", - "SrcAtop", - "SrcOver", - "SrcIn", - "SrcOut", - "Dest", - "DestAtop", - "DestOver", - "DestIn", - "DestOut", - "Clear", - "Xor", -}; - -string[] blenders = new []{ - "Normal", - "Multiply", - "Add", - "Subtract", - "Screen", - "Darken", - "Lighten", - "Overlay", - "HardLight" -}; - - foreach(var blender in blenders) - { - GeneratePixelBlenders(blender); - - foreach(var composer in composers) - { - GenerateGenericPixelBlender(blender,composer); - } - } - -#> - } +<# +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. +#> +<#@ template debug="false" hostspecific="false" language="C#" #> +<#@ assembly name="System.Core" #> +<#@ import namespace="System.Linq" #> +<#@ import namespace="System.Text" #> +<#@ import namespace="System.Collections.Generic" #> +<#@ output extension=".cs" #> +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +// + +<# +// Note use of MethodImplOptions.NoInlining. We have tests that are failing on certain architectures when +// AggresiveInlining is used. Confirmed on Intel i7-6600U in 64bit. +#> + +using System; +using System.Numerics; +using System.Runtime.CompilerServices; + +namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders +{ + internal static partial class PorterDuffFunctions + { + +<# void GeneratePixelBlenders(string blender) { #> + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 <#=blender#>Src(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return source; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 <#=blender#>SrcAtop(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Atop(backdrop, source, <#=blender#>(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 <#=blender#>SrcOver(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Over(backdrop, source, <#=blender#>(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 <#=blender#>SrcIn(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return In(backdrop, source, <#=blender#>(backdrop, source)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 <#=blender#>SrcOut(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Out(backdrop, source); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 <#=blender#>Dest(Vector4 backdrop, Vector4 source, float opacity) + { + return backdrop; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 <#=blender#>DestAtop(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Atop(source, backdrop, <#=blender#>(source, backdrop)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 <#=blender#>DestOver(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Over(source, backdrop, <#=blender#>(source, backdrop)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 <#=blender#>DestIn(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return In(source, backdrop, <#=blender#>(source, backdrop)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 <#=blender#>DestOut(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Out(source, backdrop); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 <#=blender#>Xor(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Xor(backdrop, source); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static Vector4 <#=blender#>Clear(Vector4 backdrop, Vector4 source, float opacity) + { + source.W *= opacity; + + return Clear(backdrop, source); + } +<# } #> + + +<# void GenerateGenericPixelBlender(string blender, string composer) { #> + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TPixel <#=blender#><#=composer#>(TPixel backdrop, TPixel source, float opacity) + where TPixel : struct, IPixel + { + opacity = opacity.Clamp(0, 1); + TPixel dest = default; + dest.FromScaledVector4(<#=blender#><#=composer#>(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); + return dest; + } + +<# } #> + +<# + +string[] composers = new []{ + "Src", + "SrcAtop", + "SrcOver", + "SrcIn", + "SrcOut", + "Dest", + "DestAtop", + "DestOver", + "DestIn", + "DestOut", + "Clear", + "Xor", +}; + +string[] blenders = new []{ + "Normal", + "Multiply", + "Add", + "Subtract", + "Screen", + "Darken", + "Lighten", + "Overlay", + "HardLight" +}; + + foreach(var blender in blenders) + { + GeneratePixelBlenders(blender); + + foreach(var composer in composers) + { + GenerateGenericPixelBlender(blender,composer); + } + } + +#> + } } \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.cs b/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.cs index 9d0e9d04d..9111520a0 100644 --- a/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.cs +++ b/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.cs @@ -1,238 +1,238 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Numerics; -using System.Runtime.CompilerServices; - -namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders -{ - /// - /// Collection of Porter Duff Color Blending and Alpha Composition Functions. - /// - /// - /// These functions are designed to be a general solution for all color cases, - /// that is, they take in account the alpha value of both the backdrop - /// and source, and there's no need to alpha-premultiply neither the backdrop - /// nor the source. - /// Note there are faster functions for when the backdrop color is known - /// to be opaque - /// - internal static partial class PorterDuffFunctions - { - /// - /// Source over backdrop - /// - /// Backdrop color - /// Source color - /// Output color - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector4 Normal(Vector4 backdrop, Vector4 source) - { - return source; - } - - /// - /// Source multiplied by backdrop - /// - /// Backdrop color - /// Source color - /// Output color - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector4 Multiply(Vector4 backdrop, Vector4 source) - { - return backdrop * source; - } - - /// - /// Source added to backdrop - /// - /// Backdrop color - /// Source color - /// Output color - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector4 Add(Vector4 backdrop, Vector4 source) - { - return Vector4.Min(Vector4.One, backdrop + source); - } - - /// - /// Source subtracted from backdrop - /// - /// Backdrop color - /// Source color - /// Output color - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector4 Subtract(Vector4 backdrop, Vector4 source) - { - return Vector4.Max(Vector4.Zero, backdrop - source); - } - - /// - /// Complement of source multiplied by the complement of backdrop - /// - /// Backdrop color - /// Source color - /// Output color - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector4 Screen(Vector4 backdrop, Vector4 source) - { - return Vector4.One - ((Vector4.One - backdrop) * (Vector4.One - source)); - } - - /// - /// Per element, chooses the smallest value of source and backdrop - /// - /// Backdrop color - /// Source color - /// Output color - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector4 Darken(Vector4 backdrop, Vector4 source) - { - return Vector4.Min(backdrop, source); - } - - /// - /// Per element, chooses the largest value of source and backdrop - /// - /// Backdrop color - /// Source color - /// Output color - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector4 Lighten(Vector4 backdrop, Vector4 source) - { - return Vector4.Max(backdrop, source); - } - - /// - /// Overlays source over backdrop - /// - /// Backdrop color - /// Source color - /// Output color - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector4 Overlay(Vector4 backdrop, Vector4 source) - { - float cr = OverlayValueFunction(backdrop.X, source.X); - float cg = OverlayValueFunction(backdrop.Y, source.Y); - float cb = OverlayValueFunction(backdrop.Z, source.Z); - - return Vector4.Min(Vector4.One, new Vector4(cr, cg, cb, 0)); - } - - /// - /// Hard light effect - /// - /// Backdrop color - /// Source color - /// Output color - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector4 HardLight(Vector4 backdrop, Vector4 source) - { - float cr = OverlayValueFunction(source.X, backdrop.X); - float cg = OverlayValueFunction(source.Y, backdrop.Y); - float cb = OverlayValueFunction(source.Z, backdrop.Z); - - return Vector4.Min(Vector4.One, new Vector4(cr, cg, cb, 0)); - } - - /// - /// Helper function for Overlay andHardLight modes - /// - /// Backdrop color element - /// Source color element - /// Overlay value - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static float OverlayValueFunction(float backdrop, float source) - { - return backdrop <= 0.5f ? (2 * backdrop * source) : 1 - ((2 * (1 - source)) * (1 - backdrop)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector4 Over(Vector4 dst, Vector4 src, Vector4 blend) - { - // calculate weights - float blendW = dst.W * src.W; - float dstW = dst.W - blendW; - float srcW = src.W - blendW; - - // calculate final alpha - float alpha = dstW + srcW + blendW; - - // calculate final color - Vector4 color = (dst * dstW) + (src * srcW) + (blend * blendW); - - // unpremultiply - color /= MathF.Max(alpha, Constants.Epsilon); - color.W = alpha; - - return color; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector4 Atop(Vector4 dst, Vector4 src, Vector4 blend) - { - // calculate weights - float blendW = dst.W * src.W; - float dstW = dst.W - blendW; - - // calculate final alpha - float alpha = dstW + blendW; - - // calculate final color - Vector4 color = (dst * dstW) + (blend * blendW); - - // unpremultiply - color /= MathF.Max(alpha, Constants.Epsilon); - color.W = alpha; - - return color; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector4 In(Vector4 dst, Vector4 src, Vector4 blend) - { - float alpha = dst.W * src.W; - - Vector4 color = src * alpha; // premultiply - color /= MathF.Max(alpha, Constants.Epsilon); // unpremultiply - color.W = alpha; - - return color; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector4 Out(Vector4 dst, Vector4 src) - { - float alpha = (1 - dst.W) * src.W; - - Vector4 color = src * alpha; // premultiply - color /= MathF.Max(alpha, Constants.Epsilon); // unpremultiply - color.W = alpha; - - return color; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vector4 Xor(Vector4 dst, Vector4 src) - { - float srcW = 1 - dst.W; - float dstW = 1 - src.W; - - float alpha = (src.W * srcW) + (dst.W * dstW); - Vector4 color = (src.W * src * srcW) + (dst.W * dst * dstW); - - // unpremultiply - color /= MathF.Max(alpha, Constants.Epsilon); - color.W = alpha; - - return color; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static Vector4 Clear(Vector4 backdrop, Vector4 source) - { - return Vector4.Zero; - } - } +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Numerics; +using System.Runtime.CompilerServices; + +namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders +{ + /// + /// Collection of Porter Duff Color Blending and Alpha Composition Functions. + /// + /// + /// These functions are designed to be a general solution for all color cases, + /// that is, they take in account the alpha value of both the backdrop + /// and source, and there's no need to alpha-premultiply neither the backdrop + /// nor the source. + /// Note there are faster functions for when the backdrop color is known + /// to be opaque + /// + internal static partial class PorterDuffFunctions + { + /// + /// Source over backdrop + /// + /// Backdrop color + /// Source color + /// Output color + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Normal(Vector4 backdrop, Vector4 source) + { + return source; + } + + /// + /// Source multiplied by backdrop + /// + /// Backdrop color + /// Source color + /// Output color + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Multiply(Vector4 backdrop, Vector4 source) + { + return backdrop * source; + } + + /// + /// Source added to backdrop + /// + /// Backdrop color + /// Source color + /// Output color + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Add(Vector4 backdrop, Vector4 source) + { + return Vector4.Min(Vector4.One, backdrop + source); + } + + /// + /// Source subtracted from backdrop + /// + /// Backdrop color + /// Source color + /// Output color + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Subtract(Vector4 backdrop, Vector4 source) + { + return Vector4.Max(Vector4.Zero, backdrop - source); + } + + /// + /// Complement of source multiplied by the complement of backdrop + /// + /// Backdrop color + /// Source color + /// Output color + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Screen(Vector4 backdrop, Vector4 source) + { + return Vector4.One - ((Vector4.One - backdrop) * (Vector4.One - source)); + } + + /// + /// Per element, chooses the smallest value of source and backdrop + /// + /// Backdrop color + /// Source color + /// Output color + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Darken(Vector4 backdrop, Vector4 source) + { + return Vector4.Min(backdrop, source); + } + + /// + /// Per element, chooses the largest value of source and backdrop + /// + /// Backdrop color + /// Source color + /// Output color + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Lighten(Vector4 backdrop, Vector4 source) + { + return Vector4.Max(backdrop, source); + } + + /// + /// Overlays source over backdrop + /// + /// Backdrop color + /// Source color + /// Output color + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Overlay(Vector4 backdrop, Vector4 source) + { + float cr = OverlayValueFunction(backdrop.X, source.X); + float cg = OverlayValueFunction(backdrop.Y, source.Y); + float cb = OverlayValueFunction(backdrop.Z, source.Z); + + return Vector4.Min(Vector4.One, new Vector4(cr, cg, cb, 0)); + } + + /// + /// Hard light effect + /// + /// Backdrop color + /// Source color + /// Output color + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 HardLight(Vector4 backdrop, Vector4 source) + { + float cr = OverlayValueFunction(source.X, backdrop.X); + float cg = OverlayValueFunction(source.Y, backdrop.Y); + float cb = OverlayValueFunction(source.Z, backdrop.Z); + + return Vector4.Min(Vector4.One, new Vector4(cr, cg, cb, 0)); + } + + /// + /// Helper function for Overlay andHardLight modes + /// + /// Backdrop color element + /// Source color element + /// Overlay value + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static float OverlayValueFunction(float backdrop, float source) + { + return backdrop <= 0.5f ? (2 * backdrop * source) : 1 - ((2 * (1 - source)) * (1 - backdrop)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Over(Vector4 dst, Vector4 src, Vector4 blend) + { + // calculate weights + float blendW = dst.W * src.W; + float dstW = dst.W - blendW; + float srcW = src.W - blendW; + + // calculate final alpha + float alpha = dstW + srcW + blendW; + + // calculate final color + Vector4 color = (dst * dstW) + (src * srcW) + (blend * blendW); + + // unpremultiply + color /= MathF.Max(alpha, Constants.Epsilon); + color.W = alpha; + + return color; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Atop(Vector4 dst, Vector4 src, Vector4 blend) + { + // calculate weights + float blendW = dst.W * src.W; + float dstW = dst.W - blendW; + + // calculate final alpha + float alpha = dstW + blendW; + + // calculate final color + Vector4 color = (dst * dstW) + (blend * blendW); + + // unpremultiply + color /= MathF.Max(alpha, Constants.Epsilon); + color.W = alpha; + + return color; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 In(Vector4 dst, Vector4 src, Vector4 blend) + { + float alpha = dst.W * src.W; + + Vector4 color = src * alpha; // premultiply + color /= MathF.Max(alpha, Constants.Epsilon); // unpremultiply + color.W = alpha; + + return color; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Out(Vector4 dst, Vector4 src) + { + float alpha = (1 - dst.W) * src.W; + + Vector4 color = src * alpha; // premultiply + color /= MathF.Max(alpha, Constants.Epsilon); // unpremultiply + color.W = alpha; + + return color; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Xor(Vector4 dst, Vector4 src) + { + float srcW = 1 - dst.W; + float dstW = 1 - src.W; + + float alpha = (src.W * srcW) + (dst.W * dstW); + Vector4 color = (src.W * src * srcW) + (dst.W * dst * dstW); + + // unpremultiply + color /= MathF.Max(alpha, Constants.Epsilon); + color.W = alpha; + + return color; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static Vector4 Clear(Vector4 backdrop, Vector4 source) + { + return Vector4.Zero; + } + } } \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/PixelBlender{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelBlender{TPixel}.cs index d2a6fbf50..77bee2393 100644 --- a/src/ImageSharp/PixelFormats/PixelBlender{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/PixelBlender{TPixel}.cs @@ -1,170 +1,170 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Buffers; -using System.Numerics; - -using SixLabors.ImageSharp.Memory; - -namespace SixLabors.ImageSharp.PixelFormats -{ - /// - /// Abstract base class for calling pixel composition functions - /// - /// The type of the pixel - internal abstract class PixelBlender - where TPixel : struct, IPixel - { - /// - /// Blend 2 pixels together. - /// - /// The background color. - /// The source color. - /// - /// 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. - /// - /// The final pixel value after composition - 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. - /// - 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 - /// - /// 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( - Configuration configuration, - Span destination, - ReadOnlySpan background, - ReadOnlySpan source, - ReadOnlySpan amount) - { - this.Blend(configuration, destination, background, source, amount); - } - - /// - /// Blends 2 rows together - /// - /// the pixel format of the source span - /// 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( - Configuration configuration, - 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 = - configuration.MemoryAllocator.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); - - ReadOnlySpan sourcePixels = background.Slice(0, background.Length); - PixelOperations.Instance.ToVector4(configuration, sourcePixels, backgroundSpan, PixelConversionModifiers.Scale); - ReadOnlySpan sourcePixels1 = source.Slice(0, background.Length); - PixelOperations.Instance.ToVector4(configuration, sourcePixels1, sourceSpan, PixelConversionModifiers.Scale); - - this.BlendFunction(destinationSpan, backgroundSpan, sourceSpan, amount); - - Span sourceVectors = destinationSpan.Slice(0, background.Length); - PixelOperations.Instance.FromVector4Destructive(configuration, sourceVectors, destination, PixelConversionModifiers.Scale); - } - } - - /// - /// Blends 2 rows together - /// - /// the pixel format of the source span - /// 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( - Configuration configuration, - 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 = - configuration.MemoryAllocator.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); - - ReadOnlySpan sourcePixels = background.Slice(0, background.Length); - PixelOperations.Instance.ToVector4(configuration, sourcePixels, backgroundSpan, PixelConversionModifiers.Scale); - ReadOnlySpan sourcePixels1 = source.Slice(0, background.Length); - PixelOperations.Instance.ToVector4(configuration, sourcePixels1, sourceSpan, PixelConversionModifiers.Scale); - - this.BlendFunction(destinationSpan, backgroundSpan, sourceSpan, amount); - - Span sourceVectors = destinationSpan.Slice(0, background.Length); - PixelOperations.Instance.FromVector4Destructive(configuration, sourceVectors, destination, PixelConversionModifiers.Scale); - } - } - } +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Buffers; +using System.Numerics; + +using SixLabors.ImageSharp.Memory; + +namespace SixLabors.ImageSharp.PixelFormats +{ + /// + /// Abstract base class for calling pixel composition functions + /// + /// The type of the pixel + internal abstract class PixelBlender + where TPixel : struct, IPixel + { + /// + /// Blend 2 pixels together. + /// + /// The background color. + /// The source color. + /// + /// 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. + /// + /// The final pixel value after composition + 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. + /// + 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 + /// + /// 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( + Configuration configuration, + Span destination, + ReadOnlySpan background, + ReadOnlySpan source, + ReadOnlySpan amount) + { + this.Blend(configuration, destination, background, source, amount); + } + + /// + /// Blends 2 rows together + /// + /// the pixel format of the source span + /// 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( + Configuration configuration, + 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 = + configuration.MemoryAllocator.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); + + ReadOnlySpan sourcePixels = background.Slice(0, background.Length); + PixelOperations.Instance.ToVector4(configuration, sourcePixels, backgroundSpan, PixelConversionModifiers.Scale); + ReadOnlySpan sourcePixels1 = source.Slice(0, background.Length); + PixelOperations.Instance.ToVector4(configuration, sourcePixels1, sourceSpan, PixelConversionModifiers.Scale); + + this.BlendFunction(destinationSpan, backgroundSpan, sourceSpan, amount); + + Span sourceVectors = destinationSpan.Slice(0, background.Length); + PixelOperations.Instance.FromVector4Destructive(configuration, sourceVectors, destination, PixelConversionModifiers.Scale); + } + } + + /// + /// Blends 2 rows together + /// + /// the pixel format of the source span + /// 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( + Configuration configuration, + 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 = + configuration.MemoryAllocator.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); + + ReadOnlySpan sourcePixels = background.Slice(0, background.Length); + PixelOperations.Instance.ToVector4(configuration, sourcePixels, backgroundSpan, PixelConversionModifiers.Scale); + ReadOnlySpan sourcePixels1 = source.Slice(0, background.Length); + PixelOperations.Instance.ToVector4(configuration, sourcePixels1, sourceSpan, PixelConversionModifiers.Scale); + + this.BlendFunction(destinationSpan, backgroundSpan, sourceSpan, amount); + + Span sourceVectors = destinationSpan.Slice(0, background.Length); + PixelOperations.Instance.FromVector4Destructive(configuration, sourceVectors, destination, PixelConversionModifiers.Scale); + } + } + } } \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs index 8481fc62c..5bacc6747 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs @@ -11,7 +11,6 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; - namespace SixLabors.ImageSharp.PixelFormats { /// @@ -231,7 +230,6 @@ namespace SixLabors.ImageSharp.PixelFormats { PixelOperations.Instance.ToArgb32(configuration, sourcePixels, destinationPixels); } - } } } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs index 95d85c7c8..6074e1977 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs @@ -11,7 +11,6 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; - namespace SixLabors.ImageSharp.PixelFormats { /// @@ -231,7 +230,6 @@ namespace SixLabors.ImageSharp.PixelFormats { PixelOperations.Instance.ToBgra32(configuration, sourcePixels, destinationPixels); } - } } } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray16.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray16.PixelOperations.Generated.cs index e6ed75d49..c30dfe0c0 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray16.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray16.PixelOperations.Generated.cs @@ -11,7 +11,6 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; - namespace SixLabors.ImageSharp.PixelFormats { /// @@ -194,7 +193,6 @@ namespace SixLabors.ImageSharp.PixelFormats { PixelOperations.Instance.ToGray16(configuration, sourcePixels, destinationPixels); } - } } } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray8.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray8.PixelOperations.Generated.cs index c9a3a06fe..d37a25309 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray8.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray8.PixelOperations.Generated.cs @@ -11,7 +11,6 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; - namespace SixLabors.ImageSharp.PixelFormats { /// @@ -194,7 +193,6 @@ namespace SixLabors.ImageSharp.PixelFormats { PixelOperations.Instance.ToGray8(configuration, sourcePixels, destinationPixels); } - } } } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs index ef224c02d..e5f648fcb 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs @@ -11,7 +11,6 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; - namespace SixLabors.ImageSharp.PixelFormats { /// @@ -205,7 +204,6 @@ namespace SixLabors.ImageSharp.PixelFormats { PixelOperations.Instance.ToRgb24(configuration, sourcePixels, destinationPixels); } - } } } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb48.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb48.PixelOperations.Generated.cs index 694388899..d3b2bc6f4 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb48.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb48.PixelOperations.Generated.cs @@ -11,7 +11,6 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; - namespace SixLabors.ImageSharp.PixelFormats { /// @@ -194,7 +193,6 @@ namespace SixLabors.ImageSharp.PixelFormats { PixelOperations.Instance.ToRgb48(configuration, sourcePixels, destinationPixels); } - } } } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba32.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba32.PixelOperations.Generated.cs index f0c8bc884..0da2bf244 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba32.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba32.PixelOperations.Generated.cs @@ -11,7 +11,6 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; - namespace SixLabors.ImageSharp.PixelFormats { /// @@ -220,7 +219,6 @@ namespace SixLabors.ImageSharp.PixelFormats { PixelOperations.Instance.ToRgba32(configuration, sourcePixels, destinationPixels); } - } } } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba64.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba64.PixelOperations.Generated.cs index 0faa6eb44..83f5cadd6 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba64.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba64.PixelOperations.Generated.cs @@ -11,7 +11,6 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; - namespace SixLabors.ImageSharp.PixelFormats { /// @@ -194,7 +193,6 @@ namespace SixLabors.ImageSharp.PixelFormats { PixelOperations.Instance.ToRgba64(configuration, sourcePixels, destinationPixels); } - } } } diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.PixelBenders.cs b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.PixelBenders.cs index dcddadb6a..63db674c8 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.PixelBenders.cs +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.PixelBenders.cs @@ -1,217 +1,217 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.PixelFormats.PixelBlenders; - -namespace SixLabors.ImageSharp.PixelFormats -{ - /// - /// Provides access to pixel blenders - /// - public partial class PixelOperations - where TPixel : struct, IPixel - { - /// - /// Find an instance of the pixel blender. - /// - /// the blending and composition to apply - /// A . - internal PixelBlender GetPixelBlender(GraphicsOptions options) - { - return this.GetPixelBlender(options.ColorBlendingMode, options.AlphaCompositionMode); - } - - /// - /// Find an instance of the pixel blender. - /// - /// The color blending mode to apply - /// The alpha composition mode to apply - /// A . - internal virtual PixelBlender GetPixelBlender(PixelColorBlendingMode colorMode, PixelAlphaCompositionMode alphaMode) - { - switch (alphaMode) - { - case PixelAlphaCompositionMode.Clear: - switch (colorMode) - { - case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders.MultiplyClear.Instance; - case PixelColorBlendingMode.Add: return DefaultPixelBlenders.AddClear.Instance; - case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders.SubtractClear.Instance; - case PixelColorBlendingMode.Screen: return DefaultPixelBlenders.ScreenClear.Instance; - case PixelColorBlendingMode.Darken: return DefaultPixelBlenders.DarkenClear.Instance; - case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders.LightenClear.Instance; - case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders.OverlayClear.Instance; - case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders.HardLightClear.Instance; - case PixelColorBlendingMode.Normal: - default: return DefaultPixelBlenders.NormalClear.Instance; - } - - case PixelAlphaCompositionMode.Xor: - switch (colorMode) - { - case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders.MultiplyXor.Instance; - case PixelColorBlendingMode.Add: return DefaultPixelBlenders.AddXor.Instance; - case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders.SubtractXor.Instance; - case PixelColorBlendingMode.Screen: return DefaultPixelBlenders.ScreenXor.Instance; - case PixelColorBlendingMode.Darken: return DefaultPixelBlenders.DarkenXor.Instance; - case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders.LightenXor.Instance; - case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders.OverlayXor.Instance; - case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders.HardLightXor.Instance; - case PixelColorBlendingMode.Normal: - default: return DefaultPixelBlenders.NormalXor.Instance; - } - - case PixelAlphaCompositionMode.Src: - switch (colorMode) - { - case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders.MultiplySrc.Instance; - case PixelColorBlendingMode.Add: return DefaultPixelBlenders.AddSrc.Instance; - case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders.SubtractSrc.Instance; - case PixelColorBlendingMode.Screen: return DefaultPixelBlenders.ScreenSrc.Instance; - case PixelColorBlendingMode.Darken: return DefaultPixelBlenders.DarkenSrc.Instance; - case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders.LightenSrc.Instance; - case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders.OverlaySrc.Instance; - case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders.HardLightSrc.Instance; - case PixelColorBlendingMode.Normal: - default: return DefaultPixelBlenders.NormalSrc.Instance; - } - - case PixelAlphaCompositionMode.SrcAtop: - switch (colorMode) - { - case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders.MultiplySrcAtop.Instance; - case PixelColorBlendingMode.Add: return DefaultPixelBlenders.AddSrcAtop.Instance; - case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders.SubtractSrcAtop.Instance; - case PixelColorBlendingMode.Screen: return DefaultPixelBlenders.ScreenSrcAtop.Instance; - case PixelColorBlendingMode.Darken: return DefaultPixelBlenders.DarkenSrcAtop.Instance; - case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders.LightenSrcAtop.Instance; - case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders.OverlaySrcAtop.Instance; - case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders.HardLightSrcAtop.Instance; - case PixelColorBlendingMode.Normal: - default: return DefaultPixelBlenders.NormalSrcAtop.Instance; - } - - case PixelAlphaCompositionMode.SrcIn: - switch (colorMode) - { - case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders.MultiplySrcIn.Instance; - case PixelColorBlendingMode.Add: return DefaultPixelBlenders.AddSrcIn.Instance; - case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders.SubtractSrcIn.Instance; - case PixelColorBlendingMode.Screen: return DefaultPixelBlenders.ScreenSrcIn.Instance; - case PixelColorBlendingMode.Darken: return DefaultPixelBlenders.DarkenSrcIn.Instance; - case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders.LightenSrcIn.Instance; - case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders.OverlaySrcIn.Instance; - case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders.HardLightSrcIn.Instance; - case PixelColorBlendingMode.Normal: - default: return DefaultPixelBlenders.NormalSrcIn.Instance; - } - - case PixelAlphaCompositionMode.SrcOut: - switch (colorMode) - { - case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders.MultiplySrcOut.Instance; - case PixelColorBlendingMode.Add: return DefaultPixelBlenders.AddSrcOut.Instance; - case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders.SubtractSrcOut.Instance; - case PixelColorBlendingMode.Screen: return DefaultPixelBlenders.ScreenSrcOut.Instance; - case PixelColorBlendingMode.Darken: return DefaultPixelBlenders.DarkenSrcOut.Instance; - case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders.LightenSrcOut.Instance; - case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders.OverlaySrcOut.Instance; - case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders.HardLightSrcOut.Instance; - case PixelColorBlendingMode.Normal: - default: return DefaultPixelBlenders.NormalSrcOut.Instance; - } - - case PixelAlphaCompositionMode.Dest: - switch (colorMode) - { - case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders.MultiplyDest.Instance; - case PixelColorBlendingMode.Add: return DefaultPixelBlenders.AddDest.Instance; - case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders.SubtractDest.Instance; - case PixelColorBlendingMode.Screen: return DefaultPixelBlenders.ScreenDest.Instance; - case PixelColorBlendingMode.Darken: return DefaultPixelBlenders.DarkenDest.Instance; - case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders.LightenDest.Instance; - case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders.OverlayDest.Instance; - case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders.HardLightDest.Instance; - case PixelColorBlendingMode.Normal: - default: return DefaultPixelBlenders.NormalDest.Instance; - } - - case PixelAlphaCompositionMode.DestAtop: - switch (colorMode) - { - case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders.MultiplyDestAtop.Instance; - case PixelColorBlendingMode.Add: return DefaultPixelBlenders.AddDestAtop.Instance; - case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders.SubtractDestAtop.Instance; - case PixelColorBlendingMode.Screen: return DefaultPixelBlenders.ScreenDestAtop.Instance; - case PixelColorBlendingMode.Darken: return DefaultPixelBlenders.DarkenDestAtop.Instance; - case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders.LightenDestAtop.Instance; - case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders.OverlayDestAtop.Instance; - case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders.HardLightDestAtop.Instance; - case PixelColorBlendingMode.Normal: - default: return DefaultPixelBlenders.NormalDestAtop.Instance; - } - - case PixelAlphaCompositionMode.DestIn: - switch (colorMode) - { - case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders.MultiplyDestIn.Instance; - case PixelColorBlendingMode.Add: return DefaultPixelBlenders.AddDestIn.Instance; - case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders.SubtractDestIn.Instance; - case PixelColorBlendingMode.Screen: return DefaultPixelBlenders.ScreenDestIn.Instance; - case PixelColorBlendingMode.Darken: return DefaultPixelBlenders.DarkenDestIn.Instance; - case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders.LightenDestIn.Instance; - case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders.OverlayDestIn.Instance; - case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders.HardLightDestIn.Instance; - case PixelColorBlendingMode.Normal: - default: return DefaultPixelBlenders.NormalDestIn.Instance; - } - - case PixelAlphaCompositionMode.DestOut: - switch (colorMode) - { - case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders.MultiplyDestOut.Instance; - case PixelColorBlendingMode.Add: return DefaultPixelBlenders.AddDestOut.Instance; - case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders.SubtractDestOut.Instance; - case PixelColorBlendingMode.Screen: return DefaultPixelBlenders.ScreenDestOut.Instance; - case PixelColorBlendingMode.Darken: return DefaultPixelBlenders.DarkenDestOut.Instance; - case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders.LightenDestOut.Instance; - case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders.OverlayDestOut.Instance; - case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders.HardLightDestOut.Instance; - case PixelColorBlendingMode.Normal: - default: return DefaultPixelBlenders.NormalDestOut.Instance; - } - - case PixelAlphaCompositionMode.DestOver: - switch (colorMode) - { - case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders.MultiplyDestOver.Instance; - case PixelColorBlendingMode.Add: return DefaultPixelBlenders.AddDestOver.Instance; - case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders.SubtractDestOver.Instance; - case PixelColorBlendingMode.Screen: return DefaultPixelBlenders.ScreenDestOver.Instance; - case PixelColorBlendingMode.Darken: return DefaultPixelBlenders.DarkenDestOver.Instance; - case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders.LightenDestOver.Instance; - case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders.OverlayDestOver.Instance; - case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders.HardLightDestOver.Instance; - case PixelColorBlendingMode.Normal: - default: return DefaultPixelBlenders.NormalDestOver.Instance; - } - - case PixelAlphaCompositionMode.SrcOver: - default: - switch (colorMode) - { - case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders.MultiplySrcOver.Instance; - case PixelColorBlendingMode.Add: return DefaultPixelBlenders.AddSrcOver.Instance; - case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders.SubtractSrcOver.Instance; - case PixelColorBlendingMode.Screen: return DefaultPixelBlenders.ScreenSrcOver.Instance; - case PixelColorBlendingMode.Darken: return DefaultPixelBlenders.DarkenSrcOver.Instance; - case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders.LightenSrcOver.Instance; - case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders.OverlaySrcOver.Instance; - case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders.HardLightSrcOver.Instance; - case PixelColorBlendingMode.Normal: - default: return DefaultPixelBlenders.NormalSrcOver.Instance; - } - } - } - } +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats.PixelBlenders; + +namespace SixLabors.ImageSharp.PixelFormats +{ + /// + /// Provides access to pixel blenders + /// + public partial class PixelOperations + where TPixel : struct, IPixel + { + /// + /// Find an instance of the pixel blender. + /// + /// the blending and composition to apply + /// A . + internal PixelBlender GetPixelBlender(GraphicsOptions options) + { + return this.GetPixelBlender(options.ColorBlendingMode, options.AlphaCompositionMode); + } + + /// + /// Find an instance of the pixel blender. + /// + /// The color blending mode to apply + /// The alpha composition mode to apply + /// A . + internal virtual PixelBlender GetPixelBlender(PixelColorBlendingMode colorMode, PixelAlphaCompositionMode alphaMode) + { + switch (alphaMode) + { + case PixelAlphaCompositionMode.Clear: + switch (colorMode) + { + case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders.MultiplyClear.Instance; + case PixelColorBlendingMode.Add: return DefaultPixelBlenders.AddClear.Instance; + case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders.SubtractClear.Instance; + case PixelColorBlendingMode.Screen: return DefaultPixelBlenders.ScreenClear.Instance; + case PixelColorBlendingMode.Darken: return DefaultPixelBlenders.DarkenClear.Instance; + case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders.LightenClear.Instance; + case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders.OverlayClear.Instance; + case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders.HardLightClear.Instance; + case PixelColorBlendingMode.Normal: + default: return DefaultPixelBlenders.NormalClear.Instance; + } + + case PixelAlphaCompositionMode.Xor: + switch (colorMode) + { + case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders.MultiplyXor.Instance; + case PixelColorBlendingMode.Add: return DefaultPixelBlenders.AddXor.Instance; + case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders.SubtractXor.Instance; + case PixelColorBlendingMode.Screen: return DefaultPixelBlenders.ScreenXor.Instance; + case PixelColorBlendingMode.Darken: return DefaultPixelBlenders.DarkenXor.Instance; + case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders.LightenXor.Instance; + case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders.OverlayXor.Instance; + case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders.HardLightXor.Instance; + case PixelColorBlendingMode.Normal: + default: return DefaultPixelBlenders.NormalXor.Instance; + } + + case PixelAlphaCompositionMode.Src: + switch (colorMode) + { + case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders.MultiplySrc.Instance; + case PixelColorBlendingMode.Add: return DefaultPixelBlenders.AddSrc.Instance; + case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders.SubtractSrc.Instance; + case PixelColorBlendingMode.Screen: return DefaultPixelBlenders.ScreenSrc.Instance; + case PixelColorBlendingMode.Darken: return DefaultPixelBlenders.DarkenSrc.Instance; + case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders.LightenSrc.Instance; + case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders.OverlaySrc.Instance; + case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders.HardLightSrc.Instance; + case PixelColorBlendingMode.Normal: + default: return DefaultPixelBlenders.NormalSrc.Instance; + } + + case PixelAlphaCompositionMode.SrcAtop: + switch (colorMode) + { + case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders.MultiplySrcAtop.Instance; + case PixelColorBlendingMode.Add: return DefaultPixelBlenders.AddSrcAtop.Instance; + case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders.SubtractSrcAtop.Instance; + case PixelColorBlendingMode.Screen: return DefaultPixelBlenders.ScreenSrcAtop.Instance; + case PixelColorBlendingMode.Darken: return DefaultPixelBlenders.DarkenSrcAtop.Instance; + case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders.LightenSrcAtop.Instance; + case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders.OverlaySrcAtop.Instance; + case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders.HardLightSrcAtop.Instance; + case PixelColorBlendingMode.Normal: + default: return DefaultPixelBlenders.NormalSrcAtop.Instance; + } + + case PixelAlphaCompositionMode.SrcIn: + switch (colorMode) + { + case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders.MultiplySrcIn.Instance; + case PixelColorBlendingMode.Add: return DefaultPixelBlenders.AddSrcIn.Instance; + case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders.SubtractSrcIn.Instance; + case PixelColorBlendingMode.Screen: return DefaultPixelBlenders.ScreenSrcIn.Instance; + case PixelColorBlendingMode.Darken: return DefaultPixelBlenders.DarkenSrcIn.Instance; + case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders.LightenSrcIn.Instance; + case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders.OverlaySrcIn.Instance; + case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders.HardLightSrcIn.Instance; + case PixelColorBlendingMode.Normal: + default: return DefaultPixelBlenders.NormalSrcIn.Instance; + } + + case PixelAlphaCompositionMode.SrcOut: + switch (colorMode) + { + case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders.MultiplySrcOut.Instance; + case PixelColorBlendingMode.Add: return DefaultPixelBlenders.AddSrcOut.Instance; + case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders.SubtractSrcOut.Instance; + case PixelColorBlendingMode.Screen: return DefaultPixelBlenders.ScreenSrcOut.Instance; + case PixelColorBlendingMode.Darken: return DefaultPixelBlenders.DarkenSrcOut.Instance; + case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders.LightenSrcOut.Instance; + case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders.OverlaySrcOut.Instance; + case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders.HardLightSrcOut.Instance; + case PixelColorBlendingMode.Normal: + default: return DefaultPixelBlenders.NormalSrcOut.Instance; + } + + case PixelAlphaCompositionMode.Dest: + switch (colorMode) + { + case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders.MultiplyDest.Instance; + case PixelColorBlendingMode.Add: return DefaultPixelBlenders.AddDest.Instance; + case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders.SubtractDest.Instance; + case PixelColorBlendingMode.Screen: return DefaultPixelBlenders.ScreenDest.Instance; + case PixelColorBlendingMode.Darken: return DefaultPixelBlenders.DarkenDest.Instance; + case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders.LightenDest.Instance; + case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders.OverlayDest.Instance; + case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders.HardLightDest.Instance; + case PixelColorBlendingMode.Normal: + default: return DefaultPixelBlenders.NormalDest.Instance; + } + + case PixelAlphaCompositionMode.DestAtop: + switch (colorMode) + { + case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders.MultiplyDestAtop.Instance; + case PixelColorBlendingMode.Add: return DefaultPixelBlenders.AddDestAtop.Instance; + case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders.SubtractDestAtop.Instance; + case PixelColorBlendingMode.Screen: return DefaultPixelBlenders.ScreenDestAtop.Instance; + case PixelColorBlendingMode.Darken: return DefaultPixelBlenders.DarkenDestAtop.Instance; + case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders.LightenDestAtop.Instance; + case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders.OverlayDestAtop.Instance; + case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders.HardLightDestAtop.Instance; + case PixelColorBlendingMode.Normal: + default: return DefaultPixelBlenders.NormalDestAtop.Instance; + } + + case PixelAlphaCompositionMode.DestIn: + switch (colorMode) + { + case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders.MultiplyDestIn.Instance; + case PixelColorBlendingMode.Add: return DefaultPixelBlenders.AddDestIn.Instance; + case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders.SubtractDestIn.Instance; + case PixelColorBlendingMode.Screen: return DefaultPixelBlenders.ScreenDestIn.Instance; + case PixelColorBlendingMode.Darken: return DefaultPixelBlenders.DarkenDestIn.Instance; + case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders.LightenDestIn.Instance; + case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders.OverlayDestIn.Instance; + case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders.HardLightDestIn.Instance; + case PixelColorBlendingMode.Normal: + default: return DefaultPixelBlenders.NormalDestIn.Instance; + } + + case PixelAlphaCompositionMode.DestOut: + switch (colorMode) + { + case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders.MultiplyDestOut.Instance; + case PixelColorBlendingMode.Add: return DefaultPixelBlenders.AddDestOut.Instance; + case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders.SubtractDestOut.Instance; + case PixelColorBlendingMode.Screen: return DefaultPixelBlenders.ScreenDestOut.Instance; + case PixelColorBlendingMode.Darken: return DefaultPixelBlenders.DarkenDestOut.Instance; + case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders.LightenDestOut.Instance; + case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders.OverlayDestOut.Instance; + case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders.HardLightDestOut.Instance; + case PixelColorBlendingMode.Normal: + default: return DefaultPixelBlenders.NormalDestOut.Instance; + } + + case PixelAlphaCompositionMode.DestOver: + switch (colorMode) + { + case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders.MultiplyDestOver.Instance; + case PixelColorBlendingMode.Add: return DefaultPixelBlenders.AddDestOver.Instance; + case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders.SubtractDestOver.Instance; + case PixelColorBlendingMode.Screen: return DefaultPixelBlenders.ScreenDestOver.Instance; + case PixelColorBlendingMode.Darken: return DefaultPixelBlenders.DarkenDestOver.Instance; + case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders.LightenDestOver.Instance; + case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders.OverlayDestOver.Instance; + case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders.HardLightDestOver.Instance; + case PixelColorBlendingMode.Normal: + default: return DefaultPixelBlenders.NormalDestOver.Instance; + } + + case PixelAlphaCompositionMode.SrcOver: + default: + switch (colorMode) + { + case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders.MultiplySrcOver.Instance; + case PixelColorBlendingMode.Add: return DefaultPixelBlenders.AddSrcOver.Instance; + case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders.SubtractSrcOver.Instance; + case PixelColorBlendingMode.Screen: return DefaultPixelBlenders.ScreenSrcOver.Instance; + case PixelColorBlendingMode.Darken: return DefaultPixelBlenders.DarkenSrcOver.Instance; + case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders.LightenSrcOver.Instance; + case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders.OverlaySrcOver.Instance; + case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders.HardLightSrcOver.Instance; + case PixelColorBlendingMode.Normal: + default: return DefaultPixelBlenders.NormalSrcOver.Instance; + } + } + } + } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Drawing/SolidFillBlendedShapesTests.cs b/tests/ImageSharp.Tests/Drawing/SolidFillBlendedShapesTests.cs index c34d50297..546bdef4b 100644 --- a/tests/ImageSharp.Tests/Drawing/SolidFillBlendedShapesTests.cs +++ b/tests/ImageSharp.Tests/Drawing/SolidFillBlendedShapesTests.cs @@ -1,177 +1,177 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. -using System; -using System.Collections.Generic; -using System.Linq; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; -using SixLabors.Primitives; -using Xunit; - -// ReSharper disable InconsistentNaming -namespace SixLabors.ImageSharp.Tests.Drawing -{ - [GroupOutput("Drawing")] - public class SolidFillBlendedShapesTests - { - public static IEnumerable modes = GetAllModeCombinations(); - - private static IEnumerable GetAllModeCombinations() - { - foreach (var composition in Enum.GetValues(typeof(PixelAlphaCompositionMode))) - { - foreach (var blending in Enum.GetValues(typeof(PixelColorBlendingMode))) - { - yield return new object[] { blending, composition }; - } - } - } - - - [Theory] - [WithBlankImages(nameof(modes), 250, 250, PixelTypes.Rgba32)] - public void _1DarkBlueRect_2BlendHotPinkRect( - TestImageProvider provider, - PixelColorBlendingMode blending, - PixelAlphaCompositionMode composition) - where TPixel : struct, IPixel - { - using (Image img = provider.GetImage()) - { - int scaleX = img.Width / 100; - int scaleY = img.Height / 100; - img.Mutate( - x => x.Fill( - Color.DarkBlue, - new Rectangle(0 * scaleX, 40 * scaleY, 100 * scaleX, 20 * scaleY) - ) - .Fill(new GraphicsOptions(true) { ColorBlendingMode = blending, AlphaCompositionMode=composition }, - Color.HotPink, - new Rectangle(20 * scaleX, 0 * scaleY, 30 * scaleX, 100 * scaleY)) - ); - - VerifyImage(provider, blending, composition, img); - } - } - - [Theory] - [WithBlankImages(nameof(modes), 250, 250, PixelTypes.Rgba32)] - public void _1DarkBlueRect_2BlendHotPinkRect_3BlendTransparentEllipse( - TestImageProvider provider, - PixelColorBlendingMode blending, - PixelAlphaCompositionMode composition) - where TPixel : struct, IPixel - { - using (Image img = provider.GetImage()) - { - int scaleX = img.Width / 100; - int scaleY = img.Height / 100; - img.Mutate( - x => x.Fill( - Color.DarkBlue, - new Rectangle(0 * scaleX, 40 * scaleY, 100 * scaleX, 20 * scaleY))); - img.Mutate( - x => x.Fill( - new GraphicsOptions(true) { ColorBlendingMode = blending, AlphaCompositionMode = composition }, - Color.HotPink, - new Rectangle(20 * scaleX, 0 * scaleY, 30 * scaleX, 100 * scaleY))); - img.Mutate( - x => x.Fill( - new GraphicsOptions(true) { ColorBlendingMode = blending, AlphaCompositionMode = composition }, - Color.Transparent, - new Shapes.EllipsePolygon(40 * scaleX, 50 * scaleY, 50 * scaleX, 50 * scaleY)) - ); - - VerifyImage(provider, blending, composition, img); - } - } - - [Theory] - [WithBlankImages(nameof(modes), 250, 250, PixelTypes.Rgba32)] - public void _1DarkBlueRect_2BlendHotPinkRect_3BlendSemiTransparentRedEllipse( - TestImageProvider provider, - PixelColorBlendingMode blending, - PixelAlphaCompositionMode composition) - where TPixel : struct, IPixel - { - using (Image img = provider.GetImage()) - { - int scaleX = (img.Width / 100); - int scaleY = (img.Height / 100); - img.Mutate( - x => x.Fill( - Color.DarkBlue, - new Rectangle(0 * scaleX, 40, 100 * scaleX, 20 * scaleY))); - img.Mutate( - x => x.Fill( - new GraphicsOptions(true) { ColorBlendingMode = blending, AlphaCompositionMode = composition }, - Color.HotPink, - new Rectangle(20 * scaleX, 0, 30 * scaleX, 100 * scaleY))); - - var transparentRed = Color.Red.WithAlpha(0.5f); - - img.Mutate( - x => x.Fill( - new GraphicsOptions(true) { ColorBlendingMode = blending, AlphaCompositionMode = composition }, - transparentRed, - new Shapes.EllipsePolygon(40 * scaleX, 50 * scaleY, 50 * scaleX, 50 * scaleY)) - ); - - VerifyImage(provider, blending, composition, img); ; - } - } - - [Theory] - [WithBlankImages(nameof(modes), 250, 250, PixelTypes.Rgba32)] - public void _1DarkBlueRect_2BlendBlackEllipse( - TestImageProvider provider, - PixelColorBlendingMode blending, - PixelAlphaCompositionMode composition) - where TPixel : struct, IPixel - { - using(Image dstImg = provider.GetImage(), srcImg = provider.GetImage()) - { - int scaleX = (dstImg.Width / 100); - int scaleY = (dstImg.Height / 100); - - dstImg.Mutate( - x => x.Fill( - Color.DarkBlue, - new Rectangle(0 * scaleX, 40 * scaleY, 100 * scaleX, 20 * scaleY))); - - srcImg.Mutate( - x => x.Fill( - Color.Black, - new Shapes.EllipsePolygon(40 * scaleX, 50 * scaleY, 50 * scaleX, 50 * scaleY))); - - dstImg.Mutate( - x => x.DrawImage(srcImg, new GraphicsOptions(true) { ColorBlendingMode = blending, AlphaCompositionMode = composition }) - ); - - VerifyImage(provider, blending, composition, dstImg); - } - } - - private static void VerifyImage( - TestImageProvider provider, - PixelColorBlendingMode blending, - PixelAlphaCompositionMode composition, - Image img) - where TPixel : struct, IPixel - { - img.DebugSave( - provider, - new { composition, blending }, - appendPixelTypeToFileName: false, - appendSourceFileOrDescription: false); - - var comparer = ImageComparer.TolerantPercentage(0.01f, 3); - img.CompareFirstFrameToReferenceOutput(comparer, - provider, - new { composition, blending }, - appendPixelTypeToFileName: false, - appendSourceFileOrDescription: false); - } - } +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. +using System; +using System.Collections.Generic; +using System.Linq; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; +using SixLabors.Primitives; +using Xunit; + +// ReSharper disable InconsistentNaming +namespace SixLabors.ImageSharp.Tests.Drawing +{ + [GroupOutput("Drawing")] + public class SolidFillBlendedShapesTests + { + public static IEnumerable modes = GetAllModeCombinations(); + + private static IEnumerable GetAllModeCombinations() + { + foreach (var composition in Enum.GetValues(typeof(PixelAlphaCompositionMode))) + { + foreach (var blending in Enum.GetValues(typeof(PixelColorBlendingMode))) + { + yield return new object[] { blending, composition }; + } + } + } + + + [Theory] + [WithBlankImages(nameof(modes), 250, 250, PixelTypes.Rgba32)] + public void _1DarkBlueRect_2BlendHotPinkRect( + TestImageProvider provider, + PixelColorBlendingMode blending, + PixelAlphaCompositionMode composition) + where TPixel : struct, IPixel + { + using (Image img = provider.GetImage()) + { + int scaleX = img.Width / 100; + int scaleY = img.Height / 100; + img.Mutate( + x => x.Fill( + Color.DarkBlue, + new Rectangle(0 * scaleX, 40 * scaleY, 100 * scaleX, 20 * scaleY) + ) + .Fill(new GraphicsOptions(true) { ColorBlendingMode = blending, AlphaCompositionMode=composition }, + Color.HotPink, + new Rectangle(20 * scaleX, 0 * scaleY, 30 * scaleX, 100 * scaleY)) + ); + + VerifyImage(provider, blending, composition, img); + } + } + + [Theory] + [WithBlankImages(nameof(modes), 250, 250, PixelTypes.Rgba32)] + public void _1DarkBlueRect_2BlendHotPinkRect_3BlendTransparentEllipse( + TestImageProvider provider, + PixelColorBlendingMode blending, + PixelAlphaCompositionMode composition) + where TPixel : struct, IPixel + { + using (Image img = provider.GetImage()) + { + int scaleX = img.Width / 100; + int scaleY = img.Height / 100; + img.Mutate( + x => x.Fill( + Color.DarkBlue, + new Rectangle(0 * scaleX, 40 * scaleY, 100 * scaleX, 20 * scaleY))); + img.Mutate( + x => x.Fill( + new GraphicsOptions(true) { ColorBlendingMode = blending, AlphaCompositionMode = composition }, + Color.HotPink, + new Rectangle(20 * scaleX, 0 * scaleY, 30 * scaleX, 100 * scaleY))); + img.Mutate( + x => x.Fill( + new GraphicsOptions(true) { ColorBlendingMode = blending, AlphaCompositionMode = composition }, + Color.Transparent, + new Shapes.EllipsePolygon(40 * scaleX, 50 * scaleY, 50 * scaleX, 50 * scaleY)) + ); + + VerifyImage(provider, blending, composition, img); + } + } + + [Theory] + [WithBlankImages(nameof(modes), 250, 250, PixelTypes.Rgba32)] + public void _1DarkBlueRect_2BlendHotPinkRect_3BlendSemiTransparentRedEllipse( + TestImageProvider provider, + PixelColorBlendingMode blending, + PixelAlphaCompositionMode composition) + where TPixel : struct, IPixel + { + using (Image img = provider.GetImage()) + { + int scaleX = (img.Width / 100); + int scaleY = (img.Height / 100); + img.Mutate( + x => x.Fill( + Color.DarkBlue, + new Rectangle(0 * scaleX, 40, 100 * scaleX, 20 * scaleY))); + img.Mutate( + x => x.Fill( + new GraphicsOptions(true) { ColorBlendingMode = blending, AlphaCompositionMode = composition }, + Color.HotPink, + new Rectangle(20 * scaleX, 0, 30 * scaleX, 100 * scaleY))); + + var transparentRed = Color.Red.WithAlpha(0.5f); + + img.Mutate( + x => x.Fill( + new GraphicsOptions(true) { ColorBlendingMode = blending, AlphaCompositionMode = composition }, + transparentRed, + new Shapes.EllipsePolygon(40 * scaleX, 50 * scaleY, 50 * scaleX, 50 * scaleY)) + ); + + VerifyImage(provider, blending, composition, img); ; + } + } + + [Theory] + [WithBlankImages(nameof(modes), 250, 250, PixelTypes.Rgba32)] + public void _1DarkBlueRect_2BlendBlackEllipse( + TestImageProvider provider, + PixelColorBlendingMode blending, + PixelAlphaCompositionMode composition) + where TPixel : struct, IPixel + { + using(Image dstImg = provider.GetImage(), srcImg = provider.GetImage()) + { + int scaleX = (dstImg.Width / 100); + int scaleY = (dstImg.Height / 100); + + dstImg.Mutate( + x => x.Fill( + Color.DarkBlue, + new Rectangle(0 * scaleX, 40 * scaleY, 100 * scaleX, 20 * scaleY))); + + srcImg.Mutate( + x => x.Fill( + Color.Black, + new Shapes.EllipsePolygon(40 * scaleX, 50 * scaleY, 50 * scaleX, 50 * scaleY))); + + dstImg.Mutate( + x => x.DrawImage(srcImg, new GraphicsOptions(true) { ColorBlendingMode = blending, AlphaCompositionMode = composition }) + ); + + VerifyImage(provider, blending, composition, dstImg); + } + } + + private static void VerifyImage( + TestImageProvider provider, + PixelColorBlendingMode blending, + PixelAlphaCompositionMode composition, + Image img) + where TPixel : struct, IPixel + { + img.DebugSave( + provider, + new { composition, blending }, + appendPixelTypeToFileName: false, + appendSourceFileOrDescription: false); + + var comparer = ImageComparer.TolerantPercentage(0.01f, 3); + img.CompareFirstFrameToReferenceOutput(comparer, + provider, + new { composition, blending }, + appendPixelTypeToFileName: false, + appendSourceFileOrDescription: false); + } + } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Formats/ImageFormatManagerTests.cs b/tests/ImageSharp.Tests/Formats/ImageFormatManagerTests.cs index c2100c302..8628d054a 100644 --- a/tests/ImageSharp.Tests/Formats/ImageFormatManagerTests.cs +++ b/tests/ImageSharp.Tests/Formats/ImageFormatManagerTests.cs @@ -1,146 +1,146 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.IO; -using System.Linq; -using Moq; -using SixLabors.ImageSharp.Formats; -using SixLabors.ImageSharp.Formats.Bmp; -using SixLabors.ImageSharp.Formats.Gif; -using SixLabors.ImageSharp.Formats.Jpeg; -using SixLabors.ImageSharp.Formats.Png; -using SixLabors.ImageSharp.PixelFormats; -using Xunit; - - -namespace SixLabors.ImageSharp.Tests -{ - public class ImageFormatManagerTests - { - public ImageFormatManager FormatsManagerEmpty { get; } - public ImageFormatManager DefaultFormatsManager { get; } - - public ImageFormatManagerTests() - { - this.DefaultFormatsManager = Configuration.CreateDefaultInstance().ImageFormatsManager; - this.FormatsManagerEmpty = new ImageFormatManager(); - } - - [Fact] - public void IfAutoloadWellKnownFormatsIsTrueAllFormatsAreLoaded() - { - Assert.Equal(1, this.DefaultFormatsManager.ImageEncoders.Select(item => item.Value).OfType().Count()); - Assert.Equal(1, this.DefaultFormatsManager.ImageEncoders.Select(item => item.Value).OfType().Count()); - Assert.Equal(1, this.DefaultFormatsManager.ImageEncoders.Select(item => item.Value).OfType().Count()); - Assert.Equal(1, this.DefaultFormatsManager.ImageEncoders.Select(item => item.Value).OfType().Count()); - - Assert.Equal(1, this.DefaultFormatsManager.ImageDecoders.Select(item => item.Value).OfType().Count()); - Assert.Equal(1, this.DefaultFormatsManager.ImageDecoders.Select(item => item.Value).OfType().Count()); - Assert.Equal(1, this.DefaultFormatsManager.ImageDecoders.Select(item => item.Value).OfType().Count()); - Assert.Equal(1, this.DefaultFormatsManager.ImageDecoders.Select(item => item.Value).OfType().Count()); - } - - [Fact] - public void AddImageFormatDetectorNullthrows() - { - Assert.Throws(() => - { - this.DefaultFormatsManager.AddImageFormatDetector(null); - }); - } - - [Fact] - public void RegisterNullMimeTypeEncoder() - { - Assert.Throws(() => - { - this.DefaultFormatsManager.SetEncoder(null, new Mock().Object); - }); - Assert.Throws(() => - { - this.DefaultFormatsManager.SetEncoder(BmpFormat.Instance, null); - }); - Assert.Throws(() => - { - this.DefaultFormatsManager.SetEncoder(null, null); - }); - } - - [Fact] - public void RegisterNullSetDecoder() - { - Assert.Throws(() => - { - this.DefaultFormatsManager.SetDecoder(null, new Mock().Object); - }); - Assert.Throws(() => - { - this.DefaultFormatsManager.SetDecoder(BmpFormat.Instance, null); - }); - Assert.Throws(() => - { - this.DefaultFormatsManager.SetDecoder(null, null); - }); - } - - [Fact] - public void RegisterMimeTypeEncoderReplacesLast() - { - IImageEncoder encoder1 = new Mock().Object; - this.FormatsManagerEmpty.SetEncoder(TestFormat.GlobalTestFormat, encoder1); - IImageEncoder found = this.FormatsManagerEmpty.FindEncoder(TestFormat.GlobalTestFormat); - Assert.Equal(encoder1, found); - - IImageEncoder encoder2 = new Mock().Object; - this.FormatsManagerEmpty.SetEncoder(TestFormat.GlobalTestFormat, encoder2); - IImageEncoder found2 = this.FormatsManagerEmpty.FindEncoder(TestFormat.GlobalTestFormat); - Assert.Equal(encoder2, found2); - Assert.NotEqual(found, found2); - } - - [Fact] - public void RegisterMimeTypeDecoderReplacesLast() - { - IImageDecoder decoder1 = new Mock().Object; - this.FormatsManagerEmpty.SetDecoder(TestFormat.GlobalTestFormat, decoder1); - IImageDecoder found = this.FormatsManagerEmpty.FindDecoder(TestFormat.GlobalTestFormat); - Assert.Equal(decoder1, found); - - IImageDecoder decoder2 = new Mock().Object; - this.FormatsManagerEmpty.SetDecoder(TestFormat.GlobalTestFormat, decoder2); - IImageDecoder found2 = this.FormatsManagerEmpty.FindDecoder(TestFormat.GlobalTestFormat); - Assert.Equal(decoder2, found2); - Assert.NotEqual(found, found2); - } - - [Fact] - public void AddFormatCallsConfig() - { - var provider = new Mock(); - var config = new Configuration(); - config.Configure(provider.Object); - - provider.Verify(x => x.Configure(config)); - } - - [Fact] - public void DetectFormatAllocatesCleanBuffer() - { - byte[] jpegImage; - using (var buffer = new MemoryStream()) - { - using (var image = new Image(100, 100)) - { - image.SaveAsJpeg(buffer); - jpegImage = buffer.ToArray(); - } - } - - byte[] invalidImage = { 1, 2, 3 }; - - Assert.Equal(Image.DetectFormat(jpegImage), JpegFormat.Instance); - Assert.True(Image.DetectFormat(invalidImage) is null); - } - } -} +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.IO; +using System.Linq; +using Moq; +using SixLabors.ImageSharp.Formats; +using SixLabors.ImageSharp.Formats.Bmp; +using SixLabors.ImageSharp.Formats.Gif; +using SixLabors.ImageSharp.Formats.Jpeg; +using SixLabors.ImageSharp.Formats.Png; +using SixLabors.ImageSharp.PixelFormats; +using Xunit; + + +namespace SixLabors.ImageSharp.Tests +{ + public class ImageFormatManagerTests + { + public ImageFormatManager FormatsManagerEmpty { get; } + public ImageFormatManager DefaultFormatsManager { get; } + + public ImageFormatManagerTests() + { + this.DefaultFormatsManager = Configuration.CreateDefaultInstance().ImageFormatsManager; + this.FormatsManagerEmpty = new ImageFormatManager(); + } + + [Fact] + public void IfAutoloadWellKnownFormatsIsTrueAllFormatsAreLoaded() + { + Assert.Equal(1, this.DefaultFormatsManager.ImageEncoders.Select(item => item.Value).OfType().Count()); + Assert.Equal(1, this.DefaultFormatsManager.ImageEncoders.Select(item => item.Value).OfType().Count()); + Assert.Equal(1, this.DefaultFormatsManager.ImageEncoders.Select(item => item.Value).OfType().Count()); + Assert.Equal(1, this.DefaultFormatsManager.ImageEncoders.Select(item => item.Value).OfType().Count()); + + Assert.Equal(1, this.DefaultFormatsManager.ImageDecoders.Select(item => item.Value).OfType().Count()); + Assert.Equal(1, this.DefaultFormatsManager.ImageDecoders.Select(item => item.Value).OfType().Count()); + Assert.Equal(1, this.DefaultFormatsManager.ImageDecoders.Select(item => item.Value).OfType().Count()); + Assert.Equal(1, this.DefaultFormatsManager.ImageDecoders.Select(item => item.Value).OfType().Count()); + } + + [Fact] + public void AddImageFormatDetectorNullthrows() + { + Assert.Throws(() => + { + this.DefaultFormatsManager.AddImageFormatDetector(null); + }); + } + + [Fact] + public void RegisterNullMimeTypeEncoder() + { + Assert.Throws(() => + { + this.DefaultFormatsManager.SetEncoder(null, new Mock().Object); + }); + Assert.Throws(() => + { + this.DefaultFormatsManager.SetEncoder(BmpFormat.Instance, null); + }); + Assert.Throws(() => + { + this.DefaultFormatsManager.SetEncoder(null, null); + }); + } + + [Fact] + public void RegisterNullSetDecoder() + { + Assert.Throws(() => + { + this.DefaultFormatsManager.SetDecoder(null, new Mock().Object); + }); + Assert.Throws(() => + { + this.DefaultFormatsManager.SetDecoder(BmpFormat.Instance, null); + }); + Assert.Throws(() => + { + this.DefaultFormatsManager.SetDecoder(null, null); + }); + } + + [Fact] + public void RegisterMimeTypeEncoderReplacesLast() + { + IImageEncoder encoder1 = new Mock().Object; + this.FormatsManagerEmpty.SetEncoder(TestFormat.GlobalTestFormat, encoder1); + IImageEncoder found = this.FormatsManagerEmpty.FindEncoder(TestFormat.GlobalTestFormat); + Assert.Equal(encoder1, found); + + IImageEncoder encoder2 = new Mock().Object; + this.FormatsManagerEmpty.SetEncoder(TestFormat.GlobalTestFormat, encoder2); + IImageEncoder found2 = this.FormatsManagerEmpty.FindEncoder(TestFormat.GlobalTestFormat); + Assert.Equal(encoder2, found2); + Assert.NotEqual(found, found2); + } + + [Fact] + public void RegisterMimeTypeDecoderReplacesLast() + { + IImageDecoder decoder1 = new Mock().Object; + this.FormatsManagerEmpty.SetDecoder(TestFormat.GlobalTestFormat, decoder1); + IImageDecoder found = this.FormatsManagerEmpty.FindDecoder(TestFormat.GlobalTestFormat); + Assert.Equal(decoder1, found); + + IImageDecoder decoder2 = new Mock().Object; + this.FormatsManagerEmpty.SetDecoder(TestFormat.GlobalTestFormat, decoder2); + IImageDecoder found2 = this.FormatsManagerEmpty.FindDecoder(TestFormat.GlobalTestFormat); + Assert.Equal(decoder2, found2); + Assert.NotEqual(found, found2); + } + + [Fact] + public void AddFormatCallsConfig() + { + var provider = new Mock(); + var config = new Configuration(); + config.Configure(provider.Object); + + provider.Verify(x => x.Configure(config)); + } + + [Fact] + public void DetectFormatAllocatesCleanBuffer() + { + byte[] jpegImage; + using (var buffer = new MemoryStream()) + { + using (var image = new Image(100, 100)) + { + image.SaveAsJpeg(buffer); + jpegImage = buffer.ToArray(); + } + } + + byte[] invalidImage = { 1, 2, 3 }; + + Assert.Equal(Image.DetectFormat(jpegImage), JpegFormat.Instance); + Assert.True(Image.DetectFormat(invalidImage) is null); + } + } +} diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelBlenders/PorterDuffCompositorTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelBlenders/PorterDuffCompositorTests.cs index 0c7a76081..09a78a6aa 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelBlenders/PorterDuffCompositorTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelBlenders/PorterDuffCompositorTests.cs @@ -1,56 +1,56 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders -{ - using SixLabors.ImageSharp.PixelFormats; - using SixLabors.ImageSharp.Processing; - - using Xunit; - - public class PorterDuffCompositorTests - { - // TODO: Add other modes to compare. - public static readonly TheoryData CompositingOperators = - new TheoryData - { - PixelAlphaCompositionMode.Src, - PixelAlphaCompositionMode.SrcAtop, - PixelAlphaCompositionMode.SrcOver, - PixelAlphaCompositionMode.SrcIn, - PixelAlphaCompositionMode.SrcOut, - PixelAlphaCompositionMode.Dest, - PixelAlphaCompositionMode.DestAtop, - PixelAlphaCompositionMode.DestOver, - PixelAlphaCompositionMode.DestIn, - PixelAlphaCompositionMode.DestOut, - PixelAlphaCompositionMode.Clear, - PixelAlphaCompositionMode.Xor - }; - - [Theory] - [WithFile(TestImages.Png.PDDest, nameof(CompositingOperators), PixelTypes.Rgba32)] - public void PorterDuffOutputIsCorrect(TestImageProvider provider, PixelAlphaCompositionMode mode) - { - var srcFile = TestFile.Create(TestImages.Png.PDSrc); - using (Image src = srcFile.CreateRgba32Image()) - using (Image dest = provider.GetImage()) - { - GraphicsOptions options = new GraphicsOptions - { - AlphaCompositionMode = mode - }; - - using (Image res = dest.Clone(x => x.DrawImage(src, options))) - { - string combinedMode = mode.ToString(); - - if (combinedMode != "Src" && combinedMode.StartsWith("Src")) combinedMode = combinedMode.Substring(3); - - res.DebugSave(provider, combinedMode); - res.CompareToReferenceOutput(provider, combinedMode); - } - } - } - } +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders +{ + using SixLabors.ImageSharp.PixelFormats; + using SixLabors.ImageSharp.Processing; + + using Xunit; + + public class PorterDuffCompositorTests + { + // TODO: Add other modes to compare. + public static readonly TheoryData CompositingOperators = + new TheoryData + { + PixelAlphaCompositionMode.Src, + PixelAlphaCompositionMode.SrcAtop, + PixelAlphaCompositionMode.SrcOver, + PixelAlphaCompositionMode.SrcIn, + PixelAlphaCompositionMode.SrcOut, + PixelAlphaCompositionMode.Dest, + PixelAlphaCompositionMode.DestAtop, + PixelAlphaCompositionMode.DestOver, + PixelAlphaCompositionMode.DestIn, + PixelAlphaCompositionMode.DestOut, + PixelAlphaCompositionMode.Clear, + PixelAlphaCompositionMode.Xor + }; + + [Theory] + [WithFile(TestImages.Png.PDDest, nameof(CompositingOperators), PixelTypes.Rgba32)] + public void PorterDuffOutputIsCorrect(TestImageProvider provider, PixelAlphaCompositionMode mode) + { + var srcFile = TestFile.Create(TestImages.Png.PDSrc); + using (Image src = srcFile.CreateRgba32Image()) + using (Image dest = provider.GetImage()) + { + GraphicsOptions options = new GraphicsOptions + { + AlphaCompositionMode = mode + }; + + using (Image res = dest.Clone(x => x.DrawImage(src, options))) + { + string combinedMode = mode.ToString(); + + if (combinedMode != "Src" && combinedMode.StartsWith("Src")) combinedMode = combinedMode.Substring(3); + + res.DebugSave(provider, combinedMode); + res.CompareToReferenceOutput(provider, combinedMode); + } + } + } + } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.Blender.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.Blender.cs index 3c562057a..a044ebae9 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.Blender.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.Blender.cs @@ -12,7 +12,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.PixelFormats { public class PixelBlenderTests - { + { public static TheoryData BlenderMappings = new TheoryData() { { new TestPixel(), typeof(DefaultPixelBlenders.NormalSrcOver), PixelColorBlendingMode.Normal }, @@ -43,62 +43,62 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats { PixelBlender blender = PixelOperations.Instance.GetPixelBlender(mode, PixelAlphaCompositionMode.SrcOver); Assert.IsType(type, blender); - } - - public static TheoryData ColorBlendingExpectedResults = new TheoryData() - { - { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelColorBlendingMode.Normal, Rgba32.MidnightBlue }, - { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelColorBlendingMode.Screen, new Rgba32(0xFFEEE7FF) }, - { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelColorBlendingMode.HardLight, new Rgba32(0xFFC62D32) }, - { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelColorBlendingMode.Overlay, new Rgba32(0xFFDDCEFF) }, - { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelColorBlendingMode.Darken, new Rgba32(0xFF701919) }, - { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelColorBlendingMode.Lighten, new Rgba32(0xFFE1E4FF) }, - { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelColorBlendingMode.Add, new Rgba32(0xFFFFFDFF) }, - { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelColorBlendingMode.Subtract, new Rgba32(0xFF71CBE6) }, - { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelColorBlendingMode.Multiply, new Rgba32(0xFF631619) }, - - }; - + } + + public static TheoryData ColorBlendingExpectedResults = new TheoryData() + { + { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelColorBlendingMode.Normal, Rgba32.MidnightBlue }, + { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelColorBlendingMode.Screen, new Rgba32(0xFFEEE7FF) }, + { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelColorBlendingMode.HardLight, new Rgba32(0xFFC62D32) }, + { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelColorBlendingMode.Overlay, new Rgba32(0xFFDDCEFF) }, + { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelColorBlendingMode.Darken, new Rgba32(0xFF701919) }, + { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelColorBlendingMode.Lighten, new Rgba32(0xFFE1E4FF) }, + { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelColorBlendingMode.Add, new Rgba32(0xFFFFFDFF) }, + { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelColorBlendingMode.Subtract, new Rgba32(0xFF71CBE6) }, + { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelColorBlendingMode.Multiply, new Rgba32(0xFF631619) }, + + }; + [Theory] - [MemberData(nameof(ColorBlendingExpectedResults))] - public void TestColorBlendingModes(Rgba32 backdrop, Rgba32 source, float opacity, PixelColorBlendingMode mode, Rgba32 expectedResult) - { - PixelBlender blender = PixelOperations.Instance.GetPixelBlender(mode, PixelAlphaCompositionMode.SrcOver); - - Rgba32 actualResult = blender.Blend(backdrop, source, opacity); - - // var str = actualResult.Rgba.ToString("X8"); // used to extract expectedResults - - Assert.Equal(actualResult.ToVector4(), expectedResult.ToVector4()); - } - - public static TheoryData AlphaCompositionExpectedResults = new TheoryData() - { - { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelAlphaCompositionMode.Clear, new Rgba32(0) }, - { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelAlphaCompositionMode.Xor, new Rgba32(0) }, - { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelAlphaCompositionMode.Dest, Rgba32.MistyRose }, - { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelAlphaCompositionMode.DestAtop, Rgba32.MistyRose }, - { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelAlphaCompositionMode.DestIn, Rgba32.MistyRose }, - { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelAlphaCompositionMode.DestOut, new Rgba32(0) }, - { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelAlphaCompositionMode.DestOver, Rgba32.MistyRose }, - { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelAlphaCompositionMode.Src, Rgba32.MidnightBlue }, - { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelAlphaCompositionMode.SrcAtop, Rgba32.MidnightBlue }, - { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelAlphaCompositionMode.SrcIn, Rgba32.MidnightBlue }, - { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelAlphaCompositionMode.SrcOut, new Rgba32(0) }, - { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelAlphaCompositionMode.SrcOver, Rgba32.MidnightBlue }, - }; - + [MemberData(nameof(ColorBlendingExpectedResults))] + public void TestColorBlendingModes(Rgba32 backdrop, Rgba32 source, float opacity, PixelColorBlendingMode mode, Rgba32 expectedResult) + { + PixelBlender blender = PixelOperations.Instance.GetPixelBlender(mode, PixelAlphaCompositionMode.SrcOver); + + Rgba32 actualResult = blender.Blend(backdrop, source, opacity); + + // var str = actualResult.Rgba.ToString("X8"); // used to extract expectedResults + + Assert.Equal(actualResult.ToVector4(), expectedResult.ToVector4()); + } + + public static TheoryData AlphaCompositionExpectedResults = new TheoryData() + { + { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelAlphaCompositionMode.Clear, new Rgba32(0) }, + { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelAlphaCompositionMode.Xor, new Rgba32(0) }, + { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelAlphaCompositionMode.Dest, Rgba32.MistyRose }, + { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelAlphaCompositionMode.DestAtop, Rgba32.MistyRose }, + { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelAlphaCompositionMode.DestIn, Rgba32.MistyRose }, + { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelAlphaCompositionMode.DestOut, new Rgba32(0) }, + { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelAlphaCompositionMode.DestOver, Rgba32.MistyRose }, + { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelAlphaCompositionMode.Src, Rgba32.MidnightBlue }, + { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelAlphaCompositionMode.SrcAtop, Rgba32.MidnightBlue }, + { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelAlphaCompositionMode.SrcIn, Rgba32.MidnightBlue }, + { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelAlphaCompositionMode.SrcOut, new Rgba32(0) }, + { Rgba32.MistyRose, Rgba32.MidnightBlue, 1, PixelAlphaCompositionMode.SrcOver, Rgba32.MidnightBlue }, + }; + [Theory] - [MemberData(nameof(AlphaCompositionExpectedResults))] - public void TestAlphaCompositionModes(Rgba32 backdrop, Rgba32 source, float opacity, PixelAlphaCompositionMode mode, Rgba32 expectedResult) - { - PixelBlender blender = PixelOperations.Instance.GetPixelBlender(PixelColorBlendingMode.Normal, mode); - - Rgba32 actualResult = blender.Blend(backdrop, source, opacity); - - // var str = actualResult.Rgba.ToString("X8"); // used to extract expectedResults - - Assert.Equal(actualResult.ToVector4(), expectedResult.ToVector4()); + [MemberData(nameof(AlphaCompositionExpectedResults))] + public void TestAlphaCompositionModes(Rgba32 backdrop, Rgba32 source, float opacity, PixelAlphaCompositionMode mode, Rgba32 expectedResult) + { + PixelBlender blender = PixelOperations.Instance.GetPixelBlender(PixelColorBlendingMode.Normal, mode); + + Rgba32 actualResult = blender.Blend(backdrop, source, opacity); + + // var str = actualResult.Rgba.ToString("X8"); // used to extract expectedResults + + Assert.Equal(actualResult.ToVector4(), expectedResult.ToVector4()); } } } diff --git a/tests/Images/Input/Jpg/baseline/JpegSnoopReports/Floorplan.jpg.txt b/tests/Images/Input/Jpg/baseline/JpegSnoopReports/Floorplan.jpg.txt index 2c03157af..3afec1c89 100644 --- a/tests/Images/Input/Jpg/baseline/JpegSnoopReports/Floorplan.jpg.txt +++ b/tests/Images/Input/Jpg/baseline/JpegSnoopReports/Floorplan.jpg.txt @@ -1,266 +1,266 @@ - -JPEGsnoop 1.8.0 by Calvin Hass - http://www.impulseadventure.com/photo/ - ------------------------------------- - - Filename: [.\Floorplan.jpg] - Filesize: [161577] Bytes - -Start Offset: 0x00000000 -*** Marker: SOI (xFFD8) *** - OFFSET: 0x00000000 - -*** Marker: APP0 (xFFE0) *** - OFFSET: 0x00000002 - Length = 16 - Identifier = [JFIF] - version = [1.1] - density = 300 x 300 DPI (dots per inch) - thumbnail = 0 x 0 - -*** Marker: APP1 (xFFE1) *** - OFFSET: 0x00000014 - Length = 13464 - Identifier = [Exif] - Identifier TIFF = 0x[4D4D002A 00000008] - Endian = Motorola (big) - TAG Mark x002A = 0x002A - - EXIF IFD0 @ Absolute 0x00000026 - Dir Length = 0x000A - [Model ] = "Photosmart Plus B209a-m" - [Orientation ] = 1 = Row 0: top, Col 0: left - [XResolution ] = 300/1 - [YResolution ] = 300/1 - [ResolutionUnit ] = Inch - [Software ] = "Windows Photo Editor 10.0.10011.16384" - [DateTime ] = "2016:01:02 20:17:37" - [ExifOffset ] = @ 0x091A - Offset to Next IFD = 0x000011B6 - - EXIF IFD1 @ Absolute 0x000011D4 - Dir Length = 0x0006 - [Compression ] = JPEG - [XResolution ] = 96/1 - [YResolution ] = 96/1 - [ResolutionUnit ] = Inch - [JpegIFOffset ] = @ +0x1214 = @ 0x1232 - [JpegIFByteCount ] = 0x[0000227C] / 8828 - Offset to Next IFD = 0x00000000 - - EXIF SubIFD @ Absolute 0x00000938 - Dir Length = 0x0008 - [DateTimeOriginal ] = "2016:01:02 19:22:28" - [DateTimeDigitized ] = "2016:01:02 19:22:28" - [SubSecTimeOriginal ] = "00" - [SubSecTimeDigitized ] = "00" - [ColorSpace ] = sRGB - [ExifImageWidth ] = 0x[00000922] / 2338 - [ExifImageHeight ] = 0x[000008C9] / 2249 - -*** Marker: APP1 (xFFE1) *** - OFFSET: 0x000034AE - Length = 12772 - Identifier = [http://ns.adobe.com/xap/1.0/] - XMP = - | - |Windows Photo Editor 10.0.10011.163842016-01-02T19:22:28 - -*** Marker: DQT (xFFDB) *** - Define a Quantization Table. - OFFSET: 0x00006694 - Table length = 67 - ---- - Precision=8 bits - Destination ID=0 (Luminance) - DQT, Row #0: 3 2 2 3 5 8 10 12 - DQT, Row #1: 2 2 3 4 5 12 12 11 - DQT, Row #2: 3 3 3 5 8 11 14 11 - DQT, Row #3: 3 3 4 6 10 17 16 12 - DQT, Row #4: 4 4 7 11 14 22 21 15 - DQT, Row #5: 5 7 11 13 16 21 23 18 - DQT, Row #6: 10 13 16 17 21 24 24 20 - DQT, Row #7: 14 18 19 20 22 20 21 20 - Approx quality factor = 90.06 (scaling=19.88 variance=1.14) - -*** Marker: SOF0 (Baseline DCT) (xFFC0) *** - OFFSET: 0x000066D9 - Frame header length = 11 - Precision = 8 - Number of Lines = 645 - Samples per Line = 976 - Image Size = 976 x 645 - Raw Image Orientation = Landscape - Number of Img components = 1 - Component[1]: ID=0x01, Samp Fac=0x11 (Subsamp 1 x 1), Quant Tbl Sel=0x00 (Lum: Y) - -*** Marker: DHT (Define Huffman Table) (xFFC4) *** - OFFSET: 0x000066E6 - Huffman table length = 31 - ---- - Destination ID = 0 - Class = 0 (DC / Lossless Table) - Codes of length 01 bits (000 total): - Codes of length 02 bits (001 total): 00 - Codes of length 03 bits (005 total): 01 02 03 04 05 - Codes of length 04 bits (001 total): 06 - Codes of length 05 bits (001 total): 07 - Codes of length 06 bits (001 total): 08 - Codes of length 07 bits (001 total): 09 - Codes of length 08 bits (001 total): 0A - Codes of length 09 bits (001 total): 0B - Codes of length 10 bits (000 total): - Codes of length 11 bits (000 total): - Codes of length 12 bits (000 total): - Codes of length 13 bits (000 total): - Codes of length 14 bits (000 total): - Codes of length 15 bits (000 total): - Codes of length 16 bits (000 total): - Total number of codes: 012 - - -*** Marker: DHT (Define Huffman Table) (xFFC4) *** - OFFSET: 0x00006707 - Huffman table length = 181 - ---- - Destination ID = 0 - Class = 1 (AC Table) - Codes of length 01 bits (000 total): - Codes of length 02 bits (002 total): 01 02 - Codes of length 03 bits (001 total): 03 - Codes of length 04 bits (003 total): 00 04 11 - Codes of length 05 bits (003 total): 05 12 21 - Codes of length 06 bits (002 total): 31 41 - Codes of length 07 bits (004 total): 06 13 51 61 - Codes of length 08 bits (003 total): 07 22 71 - Codes of length 09 bits (005 total): 14 32 81 91 A1 - Codes of length 10 bits (005 total): 08 23 42 B1 C1 - Codes of length 11 bits (004 total): 15 52 D1 F0 - Codes of length 12 bits (004 total): 24 33 62 72 - Codes of length 13 bits (000 total): - Codes of length 14 bits (000 total): - Codes of length 15 bits (001 total): 82 - Codes of length 16 bits (125 total): 09 0A 16 17 18 19 1A 25 26 27 28 29 2A 34 35 36 - 37 38 39 3A 43 44 45 46 47 48 49 4A 53 54 55 56 - 57 58 59 5A 63 64 65 66 67 68 69 6A 73 74 75 76 - 77 78 79 7A 83 84 85 86 87 88 89 8A 92 93 94 95 - 96 97 98 99 9A A2 A3 A4 A5 A6 A7 A8 A9 AA B2 B3 - B4 B5 B6 B7 B8 B9 BA C2 C3 C4 C5 C6 C7 C8 C9 CA - D2 D3 D4 D5 D6 D7 D8 D9 DA E1 E2 E3 E4 E5 E6 E7 - E8 E9 EA F1 F2 F3 F4 F5 F6 F7 F8 F9 FA - Total number of codes: 162 - - -*** Marker: SOS (Start of Scan) (xFFDA) *** - OFFSET: 0x000067BE - Scan header length = 8 - Number of img components = 1 - Component[1]: selector=0x01, table=0(DC),0(AC) - Spectral selection = 0 .. 63 - Successive approximation = 0x00 - - -*** Decoding SCAN Data *** - OFFSET: 0x000067C8 - Scan Decode Mode: No IDCT (DC only) - NOTE: Low-resolution DC component shown. Can decode full-res with [Options->Scan Segment->Full IDCT] - - Scan Data encountered marker 0xFFD9 @ 0x00027727.0 - - Compression stats: - Compression Ratio: 4.66:1 - Bits per pixel: 1.72:1 - - Huffman code histogram stats: - Huffman Table: (Dest ID: 0, Class: DC) - # codes of length 01 bits: 0 ( 0%) - # codes of length 02 bits: 3571 ( 36%) - # codes of length 03 bits: 4320 ( 44%) - # codes of length 04 bits: 925 ( 9%) - # codes of length 05 bits: 456 ( 5%) - # codes of length 06 bits: 313 ( 3%) - # codes of length 07 bits: 291 ( 3%) - # codes of length 08 bits: 6 ( 0%) - # codes of length 09 bits: 0 ( 0%) - # codes of length 10 bits: 0 ( 0%) - # codes of length 11 bits: 0 ( 0%) - # codes of length 12 bits: 0 ( 0%) - # codes of length 13 bits: 0 ( 0%) - # codes of length 14 bits: 0 ( 0%) - # codes of length 15 bits: 0 ( 0%) - # codes of length 16 bits: 0 ( 0%) - - Huffman Table: (Dest ID: 0, Class: AC) - # codes of length 01 bits: 0 ( 0%) - # codes of length 02 bits: 78118 ( 44%) - # codes of length 03 bits: 22349 ( 13%) - # codes of length 04 bits: 35264 ( 20%) - # codes of length 05 bits: 18811 ( 11%) - # codes of length 06 bits: 4312 ( 2%) - # codes of length 07 bits: 8245 ( 5%) - # codes of length 08 bits: 4682 ( 3%) - # codes of length 09 bits: 1584 ( 1%) - # codes of length 10 bits: 1900 ( 1%) - # codes of length 11 bits: 324 ( 0%) - # codes of length 12 bits: 116 ( 0%) - # codes of length 13 bits: 0 ( 0%) - # codes of length 14 bits: 0 ( 0%) - # codes of length 15 bits: 6 ( 0%) - # codes of length 16 bits: 639 ( 0%) - - YCC clipping in DC: - Y component: [<0= 0] [>255= 0] - Cb component: [<0= 0] [>255= 0] - Cr component: [<0= 0] [>255= 0] - - RGB clipping in DC: - R component: [<0= 0] [>255= 0] - G component: [<0= 0] [>255= 0] - B component: [<0= 0] [>255= 0] - - Average Pixel Luminance (Y): - Y=[231] (range: 0..255) - - Brightest Pixel Search: - YCC=[ 1017, 0, 0] RGB=[255,255,255] @ MCU[ 7, 0] - - Finished Decoding SCAN Data - Number of RESTART markers decoded: 0 - Next position in scan buffer: Offset 0x00027726.4 - - -*** Marker: EOI (End of Image) (xFFD9) *** - OFFSET: 0x00027727 - - -*** Searching Compression Signatures *** - - Signature: 015C645021E37D3469A6B652789383DB - Signature (Rotated): 01D400C125EB43B05762A66347B271F7 - File Offset: 0 bytes - Chroma subsampling: Gray - EXIF Make/Model: OK [???] [Photosmart Plus B209a-m] - EXIF Makernotes: NONE - EXIF Software: OK [Windows Photo Editor 10.0.10011.16384] - - Searching Compression Signatures: (3347 built-in, 0 user(*) ) - - EXIF.Make / Software EXIF.Model Quality Subsamp Match? - ------------------------- ----------------------------------- ---------------- -------------- - SW :[IJG Library ] [090 Gray ] - - The following IJG-based editors also match this signature: - SW :[GIMP ] [090 Gray ] - SW :[IrfanView ] [090 Gray ] - SW :[idImager ] [090 Gray ] - SW :[FastStone Image Viewer ] [090 Gray ] - SW :[NeatImage ] [090 Gray ] - SW :[Paint.NET ] [090 Gray ] - SW :[Photomatix ] [090 Gray ] - SW :[XnView ] [090 Gray ] - - Based on the analysis of compression characteristics and EXIF metadata: - - ASSESSMENT: Class 2 - Image has high probability of being processed/edited - - + +JPEGsnoop 1.8.0 by Calvin Hass + http://www.impulseadventure.com/photo/ + ------------------------------------- + + Filename: [.\Floorplan.jpg] + Filesize: [161577] Bytes + +Start Offset: 0x00000000 +*** Marker: SOI (xFFD8) *** + OFFSET: 0x00000000 + +*** Marker: APP0 (xFFE0) *** + OFFSET: 0x00000002 + Length = 16 + Identifier = [JFIF] + version = [1.1] + density = 300 x 300 DPI (dots per inch) + thumbnail = 0 x 0 + +*** Marker: APP1 (xFFE1) *** + OFFSET: 0x00000014 + Length = 13464 + Identifier = [Exif] + Identifier TIFF = 0x[4D4D002A 00000008] + Endian = Motorola (big) + TAG Mark x002A = 0x002A + + EXIF IFD0 @ Absolute 0x00000026 + Dir Length = 0x000A + [Model ] = "Photosmart Plus B209a-m" + [Orientation ] = 1 = Row 0: top, Col 0: left + [XResolution ] = 300/1 + [YResolution ] = 300/1 + [ResolutionUnit ] = Inch + [Software ] = "Windows Photo Editor 10.0.10011.16384" + [DateTime ] = "2016:01:02 20:17:37" + [ExifOffset ] = @ 0x091A + Offset to Next IFD = 0x000011B6 + + EXIF IFD1 @ Absolute 0x000011D4 + Dir Length = 0x0006 + [Compression ] = JPEG + [XResolution ] = 96/1 + [YResolution ] = 96/1 + [ResolutionUnit ] = Inch + [JpegIFOffset ] = @ +0x1214 = @ 0x1232 + [JpegIFByteCount ] = 0x[0000227C] / 8828 + Offset to Next IFD = 0x00000000 + + EXIF SubIFD @ Absolute 0x00000938 + Dir Length = 0x0008 + [DateTimeOriginal ] = "2016:01:02 19:22:28" + [DateTimeDigitized ] = "2016:01:02 19:22:28" + [SubSecTimeOriginal ] = "00" + [SubSecTimeDigitized ] = "00" + [ColorSpace ] = sRGB + [ExifImageWidth ] = 0x[00000922] / 2338 + [ExifImageHeight ] = 0x[000008C9] / 2249 + +*** Marker: APP1 (xFFE1) *** + OFFSET: 0x000034AE + Length = 12772 + Identifier = [http://ns.adobe.com/xap/1.0/] + XMP = + | + |Windows Photo Editor 10.0.10011.163842016-01-02T19:22:28 + +*** Marker: DQT (xFFDB) *** + Define a Quantization Table. + OFFSET: 0x00006694 + Table length = 67 + ---- + Precision=8 bits + Destination ID=0 (Luminance) + DQT, Row #0: 3 2 2 3 5 8 10 12 + DQT, Row #1: 2 2 3 4 5 12 12 11 + DQT, Row #2: 3 3 3 5 8 11 14 11 + DQT, Row #3: 3 3 4 6 10 17 16 12 + DQT, Row #4: 4 4 7 11 14 22 21 15 + DQT, Row #5: 5 7 11 13 16 21 23 18 + DQT, Row #6: 10 13 16 17 21 24 24 20 + DQT, Row #7: 14 18 19 20 22 20 21 20 + Approx quality factor = 90.06 (scaling=19.88 variance=1.14) + +*** Marker: SOF0 (Baseline DCT) (xFFC0) *** + OFFSET: 0x000066D9 + Frame header length = 11 + Precision = 8 + Number of Lines = 645 + Samples per Line = 976 + Image Size = 976 x 645 + Raw Image Orientation = Landscape + Number of Img components = 1 + Component[1]: ID=0x01, Samp Fac=0x11 (Subsamp 1 x 1), Quant Tbl Sel=0x00 (Lum: Y) + +*** Marker: DHT (Define Huffman Table) (xFFC4) *** + OFFSET: 0x000066E6 + Huffman table length = 31 + ---- + Destination ID = 0 + Class = 0 (DC / Lossless Table) + Codes of length 01 bits (000 total): + Codes of length 02 bits (001 total): 00 + Codes of length 03 bits (005 total): 01 02 03 04 05 + Codes of length 04 bits (001 total): 06 + Codes of length 05 bits (001 total): 07 + Codes of length 06 bits (001 total): 08 + Codes of length 07 bits (001 total): 09 + Codes of length 08 bits (001 total): 0A + Codes of length 09 bits (001 total): 0B + Codes of length 10 bits (000 total): + Codes of length 11 bits (000 total): + Codes of length 12 bits (000 total): + Codes of length 13 bits (000 total): + Codes of length 14 bits (000 total): + Codes of length 15 bits (000 total): + Codes of length 16 bits (000 total): + Total number of codes: 012 + + +*** Marker: DHT (Define Huffman Table) (xFFC4) *** + OFFSET: 0x00006707 + Huffman table length = 181 + ---- + Destination ID = 0 + Class = 1 (AC Table) + Codes of length 01 bits (000 total): + Codes of length 02 bits (002 total): 01 02 + Codes of length 03 bits (001 total): 03 + Codes of length 04 bits (003 total): 00 04 11 + Codes of length 05 bits (003 total): 05 12 21 + Codes of length 06 bits (002 total): 31 41 + Codes of length 07 bits (004 total): 06 13 51 61 + Codes of length 08 bits (003 total): 07 22 71 + Codes of length 09 bits (005 total): 14 32 81 91 A1 + Codes of length 10 bits (005 total): 08 23 42 B1 C1 + Codes of length 11 bits (004 total): 15 52 D1 F0 + Codes of length 12 bits (004 total): 24 33 62 72 + Codes of length 13 bits (000 total): + Codes of length 14 bits (000 total): + Codes of length 15 bits (001 total): 82 + Codes of length 16 bits (125 total): 09 0A 16 17 18 19 1A 25 26 27 28 29 2A 34 35 36 + 37 38 39 3A 43 44 45 46 47 48 49 4A 53 54 55 56 + 57 58 59 5A 63 64 65 66 67 68 69 6A 73 74 75 76 + 77 78 79 7A 83 84 85 86 87 88 89 8A 92 93 94 95 + 96 97 98 99 9A A2 A3 A4 A5 A6 A7 A8 A9 AA B2 B3 + B4 B5 B6 B7 B8 B9 BA C2 C3 C4 C5 C6 C7 C8 C9 CA + D2 D3 D4 D5 D6 D7 D8 D9 DA E1 E2 E3 E4 E5 E6 E7 + E8 E9 EA F1 F2 F3 F4 F5 F6 F7 F8 F9 FA + Total number of codes: 162 + + +*** Marker: SOS (Start of Scan) (xFFDA) *** + OFFSET: 0x000067BE + Scan header length = 8 + Number of img components = 1 + Component[1]: selector=0x01, table=0(DC),0(AC) + Spectral selection = 0 .. 63 + Successive approximation = 0x00 + + +*** Decoding SCAN Data *** + OFFSET: 0x000067C8 + Scan Decode Mode: No IDCT (DC only) + NOTE: Low-resolution DC component shown. Can decode full-res with [Options->Scan Segment->Full IDCT] + + Scan Data encountered marker 0xFFD9 @ 0x00027727.0 + + Compression stats: + Compression Ratio: 4.66:1 + Bits per pixel: 1.72:1 + + Huffman code histogram stats: + Huffman Table: (Dest ID: 0, Class: DC) + # codes of length 01 bits: 0 ( 0%) + # codes of length 02 bits: 3571 ( 36%) + # codes of length 03 bits: 4320 ( 44%) + # codes of length 04 bits: 925 ( 9%) + # codes of length 05 bits: 456 ( 5%) + # codes of length 06 bits: 313 ( 3%) + # codes of length 07 bits: 291 ( 3%) + # codes of length 08 bits: 6 ( 0%) + # codes of length 09 bits: 0 ( 0%) + # codes of length 10 bits: 0 ( 0%) + # codes of length 11 bits: 0 ( 0%) + # codes of length 12 bits: 0 ( 0%) + # codes of length 13 bits: 0 ( 0%) + # codes of length 14 bits: 0 ( 0%) + # codes of length 15 bits: 0 ( 0%) + # codes of length 16 bits: 0 ( 0%) + + Huffman Table: (Dest ID: 0, Class: AC) + # codes of length 01 bits: 0 ( 0%) + # codes of length 02 bits: 78118 ( 44%) + # codes of length 03 bits: 22349 ( 13%) + # codes of length 04 bits: 35264 ( 20%) + # codes of length 05 bits: 18811 ( 11%) + # codes of length 06 bits: 4312 ( 2%) + # codes of length 07 bits: 8245 ( 5%) + # codes of length 08 bits: 4682 ( 3%) + # codes of length 09 bits: 1584 ( 1%) + # codes of length 10 bits: 1900 ( 1%) + # codes of length 11 bits: 324 ( 0%) + # codes of length 12 bits: 116 ( 0%) + # codes of length 13 bits: 0 ( 0%) + # codes of length 14 bits: 0 ( 0%) + # codes of length 15 bits: 6 ( 0%) + # codes of length 16 bits: 639 ( 0%) + + YCC clipping in DC: + Y component: [<0= 0] [>255= 0] + Cb component: [<0= 0] [>255= 0] + Cr component: [<0= 0] [>255= 0] + + RGB clipping in DC: + R component: [<0= 0] [>255= 0] + G component: [<0= 0] [>255= 0] + B component: [<0= 0] [>255= 0] + + Average Pixel Luminance (Y): + Y=[231] (range: 0..255) + + Brightest Pixel Search: + YCC=[ 1017, 0, 0] RGB=[255,255,255] @ MCU[ 7, 0] + + Finished Decoding SCAN Data + Number of RESTART markers decoded: 0 + Next position in scan buffer: Offset 0x00027726.4 + + +*** Marker: EOI (End of Image) (xFFD9) *** + OFFSET: 0x00027727 + + +*** Searching Compression Signatures *** + + Signature: 015C645021E37D3469A6B652789383DB + Signature (Rotated): 01D400C125EB43B05762A66347B271F7 + File Offset: 0 bytes + Chroma subsampling: Gray + EXIF Make/Model: OK [???] [Photosmart Plus B209a-m] + EXIF Makernotes: NONE + EXIF Software: OK [Windows Photo Editor 10.0.10011.16384] + + Searching Compression Signatures: (3347 built-in, 0 user(*) ) + + EXIF.Make / Software EXIF.Model Quality Subsamp Match? + ------------------------- ----------------------------------- ---------------- -------------- + SW :[IJG Library ] [090 Gray ] + + The following IJG-based editors also match this signature: + SW :[GIMP ] [090 Gray ] + SW :[IrfanView ] [090 Gray ] + SW :[idImager ] [090 Gray ] + SW :[FastStone Image Viewer ] [090 Gray ] + SW :[NeatImage ] [090 Gray ] + SW :[Paint.NET ] [090 Gray ] + SW :[Photomatix ] [090 Gray ] + SW :[XnView ] [090 Gray ] + + Based on the analysis of compression characteristics and EXIF metadata: + + ASSESSMENT: Class 2 - Image has high probability of being processed/edited + + diff --git a/tests/Images/Input/Jpg/baseline/JpegSnoopReports/badrst.jpg.txt b/tests/Images/Input/Jpg/baseline/JpegSnoopReports/badrst.jpg.txt index cb74eb88f..d7c49652e 100644 --- a/tests/Images/Input/Jpg/baseline/JpegSnoopReports/badrst.jpg.txt +++ b/tests/Images/Input/Jpg/baseline/JpegSnoopReports/badrst.jpg.txt @@ -1,434 +1,434 @@ - -JPEGsnoop 1.8.0 by Calvin Hass - http://www.impulseadventure.com/photo/ - ------------------------------------- - - Filename: [.\badrst.jpg] - Filesize: [74497] Bytes - -Start Offset: 0x00000000 -*** Marker: SOI (xFFD8) *** - OFFSET: 0x00000000 - -*** Marker: APP0 (xFFE0) *** - OFFSET: 0x00000002 - Length = 16 - Identifier = [JFIF] - version = [1.1] - density = 96 x 96 DPI (dots per inch) - thumbnail = 0 x 0 - -*** Marker: APP1 (xFFE1) *** - OFFSET: 0x00000014 - Length = 8628 - Identifier = [Exif] - Identifier TIFF = 0x[4D4D002A 00000008] - Endian = Motorola (big) - TAG Mark x002A = 0x002A - - EXIF IFD0 @ Absolute 0x00000026 - Dir Length = 0x0003 - [Orientation ] = 1 = Row 0: top, Col 0: left - [ExifOffset ] = @ 0x083E - Offset to Next IFD = 0x000010B6 - - EXIF IFD1 @ Absolute 0x000010D4 - Dir Length = 0x0006 - [Compression ] = JPEG - [XResolution ] = 96/1 - [YResolution ] = 96/1 - [ResolutionUnit ] = Inch - [JpegIFOffset ] = @ +0x1114 = @ 0x1132 - [JpegIFByteCount ] = 0x[00001097] / 4247 - Offset to Next IFD = 0x00000000 - - EXIF SubIFD @ Absolute 0x0000085C - Dir Length = 0x0005 - [DateTimeOriginal ] = "2016:02:28 11:17:08" - [DateTimeDigitized ] = "2016:02:28 11:17:08" - [SubSecTimeOriginal ] = "06" - [SubSecTimeDigitized ] = "06" - -*** Marker: APP1 (xFFE1) *** - OFFSET: 0x000021CA - Length = 2464 - Identifier = [http://ns.adobe.com/xap/1.0/] - XMP = - | - |2016-02-28T11:17:08.057 - -*** Marker: DQT (xFFDB) *** - Define a Quantization Table. - OFFSET: 0x00002B6C - Table length = 67 - ---- - Precision=8 bits - Destination ID=0 (Luminance) - DQT, Row #0: 3 2 2 3 5 8 10 12 - DQT, Row #1: 2 2 3 4 5 12 12 11 - DQT, Row #2: 3 3 3 5 8 11 14 11 - DQT, Row #3: 3 3 4 6 10 17 16 12 - DQT, Row #4: 4 4 7 11 14 22 21 15 - DQT, Row #5: 5 7 11 13 16 21 23 18 - DQT, Row #6: 10 13 16 17 21 24 24 20 - DQT, Row #7: 14 18 19 20 22 20 21 20 - Approx quality factor = 90.06 (scaling=19.88 variance=1.14) - -*** Marker: DQT (xFFDB) *** - Define a Quantization Table. - OFFSET: 0x00002BB1 - Table length = 67 - ---- - Precision=8 bits - Destination ID=1 (Chrominance) - DQT, Row #0: 3 4 5 9 20 20 20 20 - DQT, Row #1: 4 4 5 13 20 20 20 20 - DQT, Row #2: 5 5 11 20 20 20 20 20 - DQT, Row #3: 9 13 20 20 20 20 20 20 - DQT, Row #4: 20 20 20 20 20 20 20 20 - DQT, Row #5: 20 20 20 20 20 20 20 20 - DQT, Row #6: 20 20 20 20 20 20 20 20 - DQT, Row #7: 20 20 20 20 20 20 20 20 - Approx quality factor = 89.93 (scaling=20.14 variance=0.34) - -*** Marker: SOF0 (Baseline DCT) (xFFC0) *** - OFFSET: 0x00002BF6 - Frame header length = 17 - Precision = 8 - Number of Lines = 480 - Samples per Line = 640 - Image Size = 640 x 480 - Raw Image Orientation = Landscape - Number of Img components = 3 - Component[1]: ID=0x01, Samp Fac=0x22 (Subsamp 1 x 1), Quant Tbl Sel=0x00 (Lum: Y) - Component[2]: ID=0x02, Samp Fac=0x11 (Subsamp 2 x 2), Quant Tbl Sel=0x01 (Chrom: Cb) - Component[3]: ID=0x03, Samp Fac=0x11 (Subsamp 2 x 2), Quant Tbl Sel=0x01 (Chrom: Cr) - -*** Marker: DHT (Define Huffman Table) (xFFC4) *** - OFFSET: 0x00002C09 - Huffman table length = 31 - ---- - Destination ID = 0 - Class = 0 (DC / Lossless Table) - Codes of length 01 bits (000 total): - Codes of length 02 bits (001 total): 00 - Codes of length 03 bits (005 total): 01 02 03 04 05 - Codes of length 04 bits (001 total): 06 - Codes of length 05 bits (001 total): 07 - Codes of length 06 bits (001 total): 08 - Codes of length 07 bits (001 total): 09 - Codes of length 08 bits (001 total): 0A - Codes of length 09 bits (001 total): 0B - Codes of length 10 bits (000 total): - Codes of length 11 bits (000 total): - Codes of length 12 bits (000 total): - Codes of length 13 bits (000 total): - Codes of length 14 bits (000 total): - Codes of length 15 bits (000 total): - Codes of length 16 bits (000 total): - Total number of codes: 012 - - -*** Marker: DHT (Define Huffman Table) (xFFC4) *** - OFFSET: 0x00002C2A - Huffman table length = 181 - ---- - Destination ID = 0 - Class = 1 (AC Table) - Codes of length 01 bits (000 total): - Codes of length 02 bits (002 total): 01 02 - Codes of length 03 bits (001 total): 03 - Codes of length 04 bits (003 total): 00 04 11 - Codes of length 05 bits (003 total): 05 12 21 - Codes of length 06 bits (002 total): 31 41 - Codes of length 07 bits (004 total): 06 13 51 61 - Codes of length 08 bits (003 total): 07 22 71 - Codes of length 09 bits (005 total): 14 32 81 91 A1 - Codes of length 10 bits (005 total): 08 23 42 B1 C1 - Codes of length 11 bits (004 total): 15 52 D1 F0 - Codes of length 12 bits (004 total): 24 33 62 72 - Codes of length 13 bits (000 total): - Codes of length 14 bits (000 total): - Codes of length 15 bits (001 total): 82 - Codes of length 16 bits (125 total): 09 0A 16 17 18 19 1A 25 26 27 28 29 2A 34 35 36 - 37 38 39 3A 43 44 45 46 47 48 49 4A 53 54 55 56 - 57 58 59 5A 63 64 65 66 67 68 69 6A 73 74 75 76 - 77 78 79 7A 83 84 85 86 87 88 89 8A 92 93 94 95 - 96 97 98 99 9A A2 A3 A4 A5 A6 A7 A8 A9 AA B2 B3 - B4 B5 B6 B7 B8 B9 BA C2 C3 C4 C5 C6 C7 C8 C9 CA - D2 D3 D4 D5 D6 D7 D8 D9 DA E1 E2 E3 E4 E5 E6 E7 - E8 E9 EA F1 F2 F3 F4 F5 F6 F7 F8 F9 FA - Total number of codes: 162 - - -*** Marker: DHT (Define Huffman Table) (xFFC4) *** - OFFSET: 0x00002CE1 - Huffman table length = 31 - ---- - Destination ID = 1 - Class = 0 (DC / Lossless Table) - Codes of length 01 bits (000 total): - Codes of length 02 bits (003 total): 00 01 02 - Codes of length 03 bits (001 total): 03 - Codes of length 04 bits (001 total): 04 - Codes of length 05 bits (001 total): 05 - Codes of length 06 bits (001 total): 06 - Codes of length 07 bits (001 total): 07 - Codes of length 08 bits (001 total): 08 - Codes of length 09 bits (001 total): 09 - Codes of length 10 bits (001 total): 0A - Codes of length 11 bits (001 total): 0B - Codes of length 12 bits (000 total): - Codes of length 13 bits (000 total): - Codes of length 14 bits (000 total): - Codes of length 15 bits (000 total): - Codes of length 16 bits (000 total): - Total number of codes: 012 - - -*** Marker: DHT (Define Huffman Table) (xFFC4) *** - OFFSET: 0x00002D02 - Huffman table length = 181 - ---- - Destination ID = 1 - Class = 1 (AC Table) - Codes of length 01 bits (000 total): - Codes of length 02 bits (002 total): 00 01 - Codes of length 03 bits (001 total): 02 - Codes of length 04 bits (002 total): 03 11 - Codes of length 05 bits (004 total): 04 05 21 31 - Codes of length 06 bits (004 total): 06 12 41 51 - Codes of length 07 bits (003 total): 07 61 71 - Codes of length 08 bits (004 total): 13 22 32 81 - Codes of length 09 bits (007 total): 08 14 42 91 A1 B1 C1 - Codes of length 10 bits (005 total): 09 23 33 52 F0 - Codes of length 11 bits (004 total): 15 62 72 D1 - Codes of length 12 bits (004 total): 0A 16 24 34 - Codes of length 13 bits (000 total): - Codes of length 14 bits (001 total): E1 - Codes of length 15 bits (002 total): 25 F1 - Codes of length 16 bits (119 total): 17 18 19 1A 26 27 28 29 2A 35 36 37 38 39 3A 43 - 44 45 46 47 48 49 4A 53 54 55 56 57 58 59 5A 63 - 64 65 66 67 68 69 6A 73 74 75 76 77 78 79 7A 82 - 83 84 85 86 87 88 89 8A 92 93 94 95 96 97 98 99 - 9A A2 A3 A4 A5 A6 A7 A8 A9 AA B2 B3 B4 B5 B6 B7 - B8 B9 BA C2 C3 C4 C5 C6 C7 C8 C9 CA D2 D3 D4 D5 - D6 D7 D8 D9 DA E2 E3 E4 E5 E6 E7 E8 E9 EA F2 F3 - F4 F5 F6 F7 F8 F9 FA - Total number of codes: 162 - - -*** Marker: DRI (Restart Interval) (xFFDD) *** - OFFSET: 0x00002DB9 - Length = 4 - interval = 600 - -*** Marker: SOS (Start of Scan) (xFFDA) *** - OFFSET: 0x00002DBF - Scan header length = 12 - Number of img components = 3 - Component[1]: selector=0x01, table=0(DC),0(AC) - Component[2]: selector=0x02, table=1(DC),1(AC) - Component[3]: selector=0x03, table=1(DC),1(AC) - Spectral selection = 0 .. 63 - Successive approximation = 0x00 - - -*** Decoding SCAN Data *** - OFFSET: 0x00002DCD - Scan Decode Mode: No IDCT (DC only) - NOTE: Low-resolution DC component shown. Can decode full-res with [Options->Scan Segment->Full IDCT] - - Expect Restart interval elapsed @ 0x00008802.4 - ERROR: Restart marker not detected -*** ERROR: Can't find huffman bitstring @ 0x00008802.5, table 0, value [0xffffffe0] -*** ERROR: Bad huffman code @ 0x00008802.4 -*** ERROR: Bad scan data in MCU(0,15): Lum CSS(0,0) @ Offset 0x00008802.5 - MCU located at pixel=(0,240) -*** ERROR: Can't find huffman bitstring @ 0x00008802.6, table 0, value [0xffffffc0] -*** ERROR: Bad huffman code @ 0x00008802.5 -*** ERROR: Bad scan data in MCU(0,15): Lum CSS(1,0) @ Offset 0x00008802.6 - MCU located at pixel=(8,240) -*** ERROR: Can't find huffman bitstring @ 0x00008802.7, table 0, value [0xffffff80] -*** ERROR: Bad huffman code @ 0x00008802.6 -*** ERROR: Bad scan data in MCU(0,15): Lum CSS(0,1) @ Offset 0x00008802.7 - MCU located at pixel=(0,248) -*** ERROR: Can't find huffman bitstring @ 0x00008803.0, table 0, value [0xffffffff] -*** ERROR: Bad huffman code @ 0x00008802.7 -*** ERROR: Bad scan data in MCU(0,15): Lum CSS(1,1) @ Offset 0x00008803.0 - MCU located at pixel=(8,248) -*** ERROR: Can't find huffman bitstring @ 0x00008803.1, table 1, value [0xfffffffe] -*** ERROR: Bad huffman code @ 0x00008803.0 -*** ERROR: Bad scan data in MCU(0,15): Chr(Cb) CSS(0,0) @ Offset 0x00008803.1 - MCU located at pixel=(0,240) -*** ERROR: Can't find huffman bitstring @ 0x00008803.2, table 1, value [0xfffffffc] -*** ERROR: Bad huffman code @ 0x00008803.1 -*** ERROR: Bad scan data in MCU(0,15): Chr(Cr) CSS(0,0) @ Offset 0x00008803.2 - MCU located at pixel=(0,240) -*** ERROR: Can't find huffman bitstring @ 0x00008803.3, table 0, value [0xfffffff8] -*** ERROR: Bad huffman code @ 0x00008803.2 - Only reported first 20 instances of this message... - - Compression stats: - Compression Ratio: 14.80:1 - Bits per pixel: 1.62:1 - - Huffman code histogram stats: - Huffman Table: (Dest ID: 0, Class: DC) - # codes of length 01 bits: 40 ( 1%) - # codes of length 02 bits: 202 ( 4%) - # codes of length 03 bits: 3515 ( 73%) - # codes of length 04 bits: 423 ( 9%) - # codes of length 05 bits: 338 ( 7%) - # codes of length 06 bits: 228 ( 5%) - # codes of length 07 bits: 54 ( 1%) - # codes of length 08 bits: 0 ( 0%) - # codes of length 09 bits: 0 ( 0%) - # codes of length 10 bits: 0 ( 0%) - # codes of length 11 bits: 0 ( 0%) - # codes of length 12 bits: 0 ( 0%) - # codes of length 13 bits: 0 ( 0%) - # codes of length 14 bits: 0 ( 0%) - # codes of length 15 bits: 0 ( 0%) - # codes of length 16 bits: 0 ( 0%) - - Huffman Table: (Dest ID: 1, Class: DC) - # codes of length 01 bits: 20 ( 1%) - # codes of length 02 bits: 1657 ( 69%) - # codes of length 03 bits: 311 ( 13%) - # codes of length 04 bits: 232 ( 10%) - # codes of length 05 bits: 123 ( 5%) - # codes of length 06 bits: 49 ( 2%) - # codes of length 07 bits: 8 ( 0%) - # codes of length 08 bits: 0 ( 0%) - # codes of length 09 bits: 0 ( 0%) - # codes of length 10 bits: 0 ( 0%) - # codes of length 11 bits: 0 ( 0%) - # codes of length 12 bits: 0 ( 0%) - # codes of length 13 bits: 0 ( 0%) - # codes of length 14 bits: 0 ( 0%) - # codes of length 15 bits: 0 ( 0%) - # codes of length 16 bits: 0 ( 0%) - - Huffman Table: (Dest ID: 0, Class: AC) - # codes of length 01 bits: 0 ( 0%) - # codes of length 02 bits: 32135 ( 43%) - # codes of length 03 bits: 8668 ( 12%) - # codes of length 04 bits: 15771 ( 21%) - # codes of length 05 bits: 7559 ( 10%) - # codes of length 06 bits: 2518 ( 3%) - # codes of length 07 bits: 3834 ( 5%) - # codes of length 08 bits: 1387 ( 2%) - # codes of length 09 bits: 1122 ( 2%) - # codes of length 10 bits: 562 ( 1%) - # codes of length 11 bits: 234 ( 0%) - # codes of length 12 bits: 131 ( 0%) - # codes of length 13 bits: 0 ( 0%) - # codes of length 14 bits: 0 ( 0%) - # codes of length 15 bits: 57 ( 0%) - # codes of length 16 bits: 286 ( 0%) - - Huffman Table: (Dest ID: 1, Class: AC) - # codes of length 01 bits: 0 ( 0%) - # codes of length 02 bits: 4525 ( 57%) - # codes of length 03 bits: 1153 ( 14%) - # codes of length 04 bits: 1341 ( 17%) - # codes of length 05 bits: 543 ( 7%) - # codes of length 06 bits: 281 ( 4%) - # codes of length 07 bits: 14 ( 0%) - # codes of length 08 bits: 93 ( 1%) - # codes of length 09 bits: 23 ( 0%) - # codes of length 10 bits: 3 ( 0%) - # codes of length 11 bits: 3 ( 0%) - # codes of length 12 bits: 0 ( 0%) - # codes of length 13 bits: 0 ( 0%) - # codes of length 14 bits: 2 ( 0%) - # codes of length 15 bits: 0 ( 0%) - # codes of length 16 bits: 0 ( 0%) - - YCC clipping in DC: - Y component: [<0= 0] [>255= 0] - Cb component: [<0= 0] [>255= 0] - Cr component: [<0= 0] [>255= 0] - - RGB clipping in DC: - R component: [<0= 0] [>255= 0] - G component: [<0= 0] [>255= 0] - B component: [<0= 0] [>255= 0] - - Average Pixel Luminance (Y): - Y=[103] (range: 0..255) - - Brightest Pixel Search: - YCC=[ 1014, -3, -27] RGB=[248,255,252] @ MCU[ 0, 13] - - Finished Decoding SCAN Data - Number of RESTART markers decoded: 1 - Next position in scan buffer: Offset 0x0001210E.0 - - -*** Skipped 10 marker pad bytes *** -*** Marker: RST# *** - OFFSET: 0x0000880D - WARNING: Restart marker [0xFFD0] detected outside scan - Stopping decode - Use [Img Search Fwd/Rev] to locate other valid embedded JPEGs - -*** Searching Compression Signatures *** - - Signature: 013BA18D5561625796E986FDBC09F846 - Signature (Rotated): 01AC57E12793DFA7C46C704625C5AF0F - File Offset: 0 bytes - Chroma subsampling: 2x2 - EXIF Make/Model: NONE - EXIF Makernotes: NONE - EXIF Software: NONE - - Searching Compression Signatures: (3347 built-in, 0 user(*) ) - - EXIF.Make / Software EXIF.Model Quality Subsamp Match? - ------------------------- ----------------------------------- ---------------- -------------- - CAM:[??? ] [Treo 680 ] [ ] Yes - CAM:[Canon ] [Canon PowerShot Pro1 ] [fine ] No - CAM:[NIKON ] [E2500 ] [FINE ] No - CAM:[NIKON ] [E3100 ] [FINE ] No - CAM:[NIKON ] [E4500 ] [FINE ] No - CAM:[NIKON ] [E5000 ] [FINE ] No - CAM:[NIKON ] [E5700 ] [FINE ] No - CAM:[NIKON ] [E775 ] [FINE ] No - CAM:[NIKON ] [E885 ] [FINE ] No - CAM:[OLYMPUS OPTICAL CO.,LTD ] [C3040Z ] [ ] No - CAM:[PENTAX ] [PENTAX Optio 550 ] [ ] No - CAM:[Research In Motion ] [BlackBerry 9530 ] [Superfine ] Yes - CAM:[SEIKO EPSON CORP. ] [PhotoPC 3000Z ] [ ] No - CAM:[SONY ] [DSC-H7 ] [ ] No - CAM:[SONY ] [DSC-H9 ] [ ] No - CAM:[SONY ] [DSC-S90 ] [ ] No - CAM:[SONY ] [DSC-W1 ] [ ] No - CAM:[SONY ] [SONY ] [ ] No - SW :[ACDSee ] [ ] - SW :[FixFoto ] [fine ] - SW :[IJG Library ] [090 ] - SW :[ZoomBrowser EX ] [high ] - - The following IJG-based editors also match this signature: - SW :[GIMP ] [090 ] - SW :[IrfanView ] [090 ] - SW :[idImager ] [090 ] - SW :[FastStone Image Viewer ] [090 ] - SW :[NeatImage ] [090 ] - SW :[Paint.NET ] [090 ] - SW :[Photomatix ] [090 ] - SW :[XnView ] [090 ] - - Based on the analysis of compression characteristics and EXIF metadata: - - ASSESSMENT: Class 1 - Image is processed/edited - - This may be a new software editor for the database. - If this file is processed, and editor doesn't appear in list above, - PLEASE ADD TO DATABASE with [Tools->Add Camera to DB] - - -*** Additional Info *** -NOTE: Data exists after EOF, range: 0x00000000-0x00012301 (74497 bytes) + +JPEGsnoop 1.8.0 by Calvin Hass + http://www.impulseadventure.com/photo/ + ------------------------------------- + + Filename: [.\badrst.jpg] + Filesize: [74497] Bytes + +Start Offset: 0x00000000 +*** Marker: SOI (xFFD8) *** + OFFSET: 0x00000000 + +*** Marker: APP0 (xFFE0) *** + OFFSET: 0x00000002 + Length = 16 + Identifier = [JFIF] + version = [1.1] + density = 96 x 96 DPI (dots per inch) + thumbnail = 0 x 0 + +*** Marker: APP1 (xFFE1) *** + OFFSET: 0x00000014 + Length = 8628 + Identifier = [Exif] + Identifier TIFF = 0x[4D4D002A 00000008] + Endian = Motorola (big) + TAG Mark x002A = 0x002A + + EXIF IFD0 @ Absolute 0x00000026 + Dir Length = 0x0003 + [Orientation ] = 1 = Row 0: top, Col 0: left + [ExifOffset ] = @ 0x083E + Offset to Next IFD = 0x000010B6 + + EXIF IFD1 @ Absolute 0x000010D4 + Dir Length = 0x0006 + [Compression ] = JPEG + [XResolution ] = 96/1 + [YResolution ] = 96/1 + [ResolutionUnit ] = Inch + [JpegIFOffset ] = @ +0x1114 = @ 0x1132 + [JpegIFByteCount ] = 0x[00001097] / 4247 + Offset to Next IFD = 0x00000000 + + EXIF SubIFD @ Absolute 0x0000085C + Dir Length = 0x0005 + [DateTimeOriginal ] = "2016:02:28 11:17:08" + [DateTimeDigitized ] = "2016:02:28 11:17:08" + [SubSecTimeOriginal ] = "06" + [SubSecTimeDigitized ] = "06" + +*** Marker: APP1 (xFFE1) *** + OFFSET: 0x000021CA + Length = 2464 + Identifier = [http://ns.adobe.com/xap/1.0/] + XMP = + | + |2016-02-28T11:17:08.057 + +*** Marker: DQT (xFFDB) *** + Define a Quantization Table. + OFFSET: 0x00002B6C + Table length = 67 + ---- + Precision=8 bits + Destination ID=0 (Luminance) + DQT, Row #0: 3 2 2 3 5 8 10 12 + DQT, Row #1: 2 2 3 4 5 12 12 11 + DQT, Row #2: 3 3 3 5 8 11 14 11 + DQT, Row #3: 3 3 4 6 10 17 16 12 + DQT, Row #4: 4 4 7 11 14 22 21 15 + DQT, Row #5: 5 7 11 13 16 21 23 18 + DQT, Row #6: 10 13 16 17 21 24 24 20 + DQT, Row #7: 14 18 19 20 22 20 21 20 + Approx quality factor = 90.06 (scaling=19.88 variance=1.14) + +*** Marker: DQT (xFFDB) *** + Define a Quantization Table. + OFFSET: 0x00002BB1 + Table length = 67 + ---- + Precision=8 bits + Destination ID=1 (Chrominance) + DQT, Row #0: 3 4 5 9 20 20 20 20 + DQT, Row #1: 4 4 5 13 20 20 20 20 + DQT, Row #2: 5 5 11 20 20 20 20 20 + DQT, Row #3: 9 13 20 20 20 20 20 20 + DQT, Row #4: 20 20 20 20 20 20 20 20 + DQT, Row #5: 20 20 20 20 20 20 20 20 + DQT, Row #6: 20 20 20 20 20 20 20 20 + DQT, Row #7: 20 20 20 20 20 20 20 20 + Approx quality factor = 89.93 (scaling=20.14 variance=0.34) + +*** Marker: SOF0 (Baseline DCT) (xFFC0) *** + OFFSET: 0x00002BF6 + Frame header length = 17 + Precision = 8 + Number of Lines = 480 + Samples per Line = 640 + Image Size = 640 x 480 + Raw Image Orientation = Landscape + Number of Img components = 3 + Component[1]: ID=0x01, Samp Fac=0x22 (Subsamp 1 x 1), Quant Tbl Sel=0x00 (Lum: Y) + Component[2]: ID=0x02, Samp Fac=0x11 (Subsamp 2 x 2), Quant Tbl Sel=0x01 (Chrom: Cb) + Component[3]: ID=0x03, Samp Fac=0x11 (Subsamp 2 x 2), Quant Tbl Sel=0x01 (Chrom: Cr) + +*** Marker: DHT (Define Huffman Table) (xFFC4) *** + OFFSET: 0x00002C09 + Huffman table length = 31 + ---- + Destination ID = 0 + Class = 0 (DC / Lossless Table) + Codes of length 01 bits (000 total): + Codes of length 02 bits (001 total): 00 + Codes of length 03 bits (005 total): 01 02 03 04 05 + Codes of length 04 bits (001 total): 06 + Codes of length 05 bits (001 total): 07 + Codes of length 06 bits (001 total): 08 + Codes of length 07 bits (001 total): 09 + Codes of length 08 bits (001 total): 0A + Codes of length 09 bits (001 total): 0B + Codes of length 10 bits (000 total): + Codes of length 11 bits (000 total): + Codes of length 12 bits (000 total): + Codes of length 13 bits (000 total): + Codes of length 14 bits (000 total): + Codes of length 15 bits (000 total): + Codes of length 16 bits (000 total): + Total number of codes: 012 + + +*** Marker: DHT (Define Huffman Table) (xFFC4) *** + OFFSET: 0x00002C2A + Huffman table length = 181 + ---- + Destination ID = 0 + Class = 1 (AC Table) + Codes of length 01 bits (000 total): + Codes of length 02 bits (002 total): 01 02 + Codes of length 03 bits (001 total): 03 + Codes of length 04 bits (003 total): 00 04 11 + Codes of length 05 bits (003 total): 05 12 21 + Codes of length 06 bits (002 total): 31 41 + Codes of length 07 bits (004 total): 06 13 51 61 + Codes of length 08 bits (003 total): 07 22 71 + Codes of length 09 bits (005 total): 14 32 81 91 A1 + Codes of length 10 bits (005 total): 08 23 42 B1 C1 + Codes of length 11 bits (004 total): 15 52 D1 F0 + Codes of length 12 bits (004 total): 24 33 62 72 + Codes of length 13 bits (000 total): + Codes of length 14 bits (000 total): + Codes of length 15 bits (001 total): 82 + Codes of length 16 bits (125 total): 09 0A 16 17 18 19 1A 25 26 27 28 29 2A 34 35 36 + 37 38 39 3A 43 44 45 46 47 48 49 4A 53 54 55 56 + 57 58 59 5A 63 64 65 66 67 68 69 6A 73 74 75 76 + 77 78 79 7A 83 84 85 86 87 88 89 8A 92 93 94 95 + 96 97 98 99 9A A2 A3 A4 A5 A6 A7 A8 A9 AA B2 B3 + B4 B5 B6 B7 B8 B9 BA C2 C3 C4 C5 C6 C7 C8 C9 CA + D2 D3 D4 D5 D6 D7 D8 D9 DA E1 E2 E3 E4 E5 E6 E7 + E8 E9 EA F1 F2 F3 F4 F5 F6 F7 F8 F9 FA + Total number of codes: 162 + + +*** Marker: DHT (Define Huffman Table) (xFFC4) *** + OFFSET: 0x00002CE1 + Huffman table length = 31 + ---- + Destination ID = 1 + Class = 0 (DC / Lossless Table) + Codes of length 01 bits (000 total): + Codes of length 02 bits (003 total): 00 01 02 + Codes of length 03 bits (001 total): 03 + Codes of length 04 bits (001 total): 04 + Codes of length 05 bits (001 total): 05 + Codes of length 06 bits (001 total): 06 + Codes of length 07 bits (001 total): 07 + Codes of length 08 bits (001 total): 08 + Codes of length 09 bits (001 total): 09 + Codes of length 10 bits (001 total): 0A + Codes of length 11 bits (001 total): 0B + Codes of length 12 bits (000 total): + Codes of length 13 bits (000 total): + Codes of length 14 bits (000 total): + Codes of length 15 bits (000 total): + Codes of length 16 bits (000 total): + Total number of codes: 012 + + +*** Marker: DHT (Define Huffman Table) (xFFC4) *** + OFFSET: 0x00002D02 + Huffman table length = 181 + ---- + Destination ID = 1 + Class = 1 (AC Table) + Codes of length 01 bits (000 total): + Codes of length 02 bits (002 total): 00 01 + Codes of length 03 bits (001 total): 02 + Codes of length 04 bits (002 total): 03 11 + Codes of length 05 bits (004 total): 04 05 21 31 + Codes of length 06 bits (004 total): 06 12 41 51 + Codes of length 07 bits (003 total): 07 61 71 + Codes of length 08 bits (004 total): 13 22 32 81 + Codes of length 09 bits (007 total): 08 14 42 91 A1 B1 C1 + Codes of length 10 bits (005 total): 09 23 33 52 F0 + Codes of length 11 bits (004 total): 15 62 72 D1 + Codes of length 12 bits (004 total): 0A 16 24 34 + Codes of length 13 bits (000 total): + Codes of length 14 bits (001 total): E1 + Codes of length 15 bits (002 total): 25 F1 + Codes of length 16 bits (119 total): 17 18 19 1A 26 27 28 29 2A 35 36 37 38 39 3A 43 + 44 45 46 47 48 49 4A 53 54 55 56 57 58 59 5A 63 + 64 65 66 67 68 69 6A 73 74 75 76 77 78 79 7A 82 + 83 84 85 86 87 88 89 8A 92 93 94 95 96 97 98 99 + 9A A2 A3 A4 A5 A6 A7 A8 A9 AA B2 B3 B4 B5 B6 B7 + B8 B9 BA C2 C3 C4 C5 C6 C7 C8 C9 CA D2 D3 D4 D5 + D6 D7 D8 D9 DA E2 E3 E4 E5 E6 E7 E8 E9 EA F2 F3 + F4 F5 F6 F7 F8 F9 FA + Total number of codes: 162 + + +*** Marker: DRI (Restart Interval) (xFFDD) *** + OFFSET: 0x00002DB9 + Length = 4 + interval = 600 + +*** Marker: SOS (Start of Scan) (xFFDA) *** + OFFSET: 0x00002DBF + Scan header length = 12 + Number of img components = 3 + Component[1]: selector=0x01, table=0(DC),0(AC) + Component[2]: selector=0x02, table=1(DC),1(AC) + Component[3]: selector=0x03, table=1(DC),1(AC) + Spectral selection = 0 .. 63 + Successive approximation = 0x00 + + +*** Decoding SCAN Data *** + OFFSET: 0x00002DCD + Scan Decode Mode: No IDCT (DC only) + NOTE: Low-resolution DC component shown. Can decode full-res with [Options->Scan Segment->Full IDCT] + + Expect Restart interval elapsed @ 0x00008802.4 + ERROR: Restart marker not detected +*** ERROR: Can't find huffman bitstring @ 0x00008802.5, table 0, value [0xffffffe0] +*** ERROR: Bad huffman code @ 0x00008802.4 +*** ERROR: Bad scan data in MCU(0,15): Lum CSS(0,0) @ Offset 0x00008802.5 + MCU located at pixel=(0,240) +*** ERROR: Can't find huffman bitstring @ 0x00008802.6, table 0, value [0xffffffc0] +*** ERROR: Bad huffman code @ 0x00008802.5 +*** ERROR: Bad scan data in MCU(0,15): Lum CSS(1,0) @ Offset 0x00008802.6 + MCU located at pixel=(8,240) +*** ERROR: Can't find huffman bitstring @ 0x00008802.7, table 0, value [0xffffff80] +*** ERROR: Bad huffman code @ 0x00008802.6 +*** ERROR: Bad scan data in MCU(0,15): Lum CSS(0,1) @ Offset 0x00008802.7 + MCU located at pixel=(0,248) +*** ERROR: Can't find huffman bitstring @ 0x00008803.0, table 0, value [0xffffffff] +*** ERROR: Bad huffman code @ 0x00008802.7 +*** ERROR: Bad scan data in MCU(0,15): Lum CSS(1,1) @ Offset 0x00008803.0 + MCU located at pixel=(8,248) +*** ERROR: Can't find huffman bitstring @ 0x00008803.1, table 1, value [0xfffffffe] +*** ERROR: Bad huffman code @ 0x00008803.0 +*** ERROR: Bad scan data in MCU(0,15): Chr(Cb) CSS(0,0) @ Offset 0x00008803.1 + MCU located at pixel=(0,240) +*** ERROR: Can't find huffman bitstring @ 0x00008803.2, table 1, value [0xfffffffc] +*** ERROR: Bad huffman code @ 0x00008803.1 +*** ERROR: Bad scan data in MCU(0,15): Chr(Cr) CSS(0,0) @ Offset 0x00008803.2 + MCU located at pixel=(0,240) +*** ERROR: Can't find huffman bitstring @ 0x00008803.3, table 0, value [0xfffffff8] +*** ERROR: Bad huffman code @ 0x00008803.2 + Only reported first 20 instances of this message... + + Compression stats: + Compression Ratio: 14.80:1 + Bits per pixel: 1.62:1 + + Huffman code histogram stats: + Huffman Table: (Dest ID: 0, Class: DC) + # codes of length 01 bits: 40 ( 1%) + # codes of length 02 bits: 202 ( 4%) + # codes of length 03 bits: 3515 ( 73%) + # codes of length 04 bits: 423 ( 9%) + # codes of length 05 bits: 338 ( 7%) + # codes of length 06 bits: 228 ( 5%) + # codes of length 07 bits: 54 ( 1%) + # codes of length 08 bits: 0 ( 0%) + # codes of length 09 bits: 0 ( 0%) + # codes of length 10 bits: 0 ( 0%) + # codes of length 11 bits: 0 ( 0%) + # codes of length 12 bits: 0 ( 0%) + # codes of length 13 bits: 0 ( 0%) + # codes of length 14 bits: 0 ( 0%) + # codes of length 15 bits: 0 ( 0%) + # codes of length 16 bits: 0 ( 0%) + + Huffman Table: (Dest ID: 1, Class: DC) + # codes of length 01 bits: 20 ( 1%) + # codes of length 02 bits: 1657 ( 69%) + # codes of length 03 bits: 311 ( 13%) + # codes of length 04 bits: 232 ( 10%) + # codes of length 05 bits: 123 ( 5%) + # codes of length 06 bits: 49 ( 2%) + # codes of length 07 bits: 8 ( 0%) + # codes of length 08 bits: 0 ( 0%) + # codes of length 09 bits: 0 ( 0%) + # codes of length 10 bits: 0 ( 0%) + # codes of length 11 bits: 0 ( 0%) + # codes of length 12 bits: 0 ( 0%) + # codes of length 13 bits: 0 ( 0%) + # codes of length 14 bits: 0 ( 0%) + # codes of length 15 bits: 0 ( 0%) + # codes of length 16 bits: 0 ( 0%) + + Huffman Table: (Dest ID: 0, Class: AC) + # codes of length 01 bits: 0 ( 0%) + # codes of length 02 bits: 32135 ( 43%) + # codes of length 03 bits: 8668 ( 12%) + # codes of length 04 bits: 15771 ( 21%) + # codes of length 05 bits: 7559 ( 10%) + # codes of length 06 bits: 2518 ( 3%) + # codes of length 07 bits: 3834 ( 5%) + # codes of length 08 bits: 1387 ( 2%) + # codes of length 09 bits: 1122 ( 2%) + # codes of length 10 bits: 562 ( 1%) + # codes of length 11 bits: 234 ( 0%) + # codes of length 12 bits: 131 ( 0%) + # codes of length 13 bits: 0 ( 0%) + # codes of length 14 bits: 0 ( 0%) + # codes of length 15 bits: 57 ( 0%) + # codes of length 16 bits: 286 ( 0%) + + Huffman Table: (Dest ID: 1, Class: AC) + # codes of length 01 bits: 0 ( 0%) + # codes of length 02 bits: 4525 ( 57%) + # codes of length 03 bits: 1153 ( 14%) + # codes of length 04 bits: 1341 ( 17%) + # codes of length 05 bits: 543 ( 7%) + # codes of length 06 bits: 281 ( 4%) + # codes of length 07 bits: 14 ( 0%) + # codes of length 08 bits: 93 ( 1%) + # codes of length 09 bits: 23 ( 0%) + # codes of length 10 bits: 3 ( 0%) + # codes of length 11 bits: 3 ( 0%) + # codes of length 12 bits: 0 ( 0%) + # codes of length 13 bits: 0 ( 0%) + # codes of length 14 bits: 2 ( 0%) + # codes of length 15 bits: 0 ( 0%) + # codes of length 16 bits: 0 ( 0%) + + YCC clipping in DC: + Y component: [<0= 0] [>255= 0] + Cb component: [<0= 0] [>255= 0] + Cr component: [<0= 0] [>255= 0] + + RGB clipping in DC: + R component: [<0= 0] [>255= 0] + G component: [<0= 0] [>255= 0] + B component: [<0= 0] [>255= 0] + + Average Pixel Luminance (Y): + Y=[103] (range: 0..255) + + Brightest Pixel Search: + YCC=[ 1014, -3, -27] RGB=[248,255,252] @ MCU[ 0, 13] + + Finished Decoding SCAN Data + Number of RESTART markers decoded: 1 + Next position in scan buffer: Offset 0x0001210E.0 + + +*** Skipped 10 marker pad bytes *** +*** Marker: RST# *** + OFFSET: 0x0000880D + WARNING: Restart marker [0xFFD0] detected outside scan + Stopping decode + Use [Img Search Fwd/Rev] to locate other valid embedded JPEGs + +*** Searching Compression Signatures *** + + Signature: 013BA18D5561625796E986FDBC09F846 + Signature (Rotated): 01AC57E12793DFA7C46C704625C5AF0F + File Offset: 0 bytes + Chroma subsampling: 2x2 + EXIF Make/Model: NONE + EXIF Makernotes: NONE + EXIF Software: NONE + + Searching Compression Signatures: (3347 built-in, 0 user(*) ) + + EXIF.Make / Software EXIF.Model Quality Subsamp Match? + ------------------------- ----------------------------------- ---------------- -------------- + CAM:[??? ] [Treo 680 ] [ ] Yes + CAM:[Canon ] [Canon PowerShot Pro1 ] [fine ] No + CAM:[NIKON ] [E2500 ] [FINE ] No + CAM:[NIKON ] [E3100 ] [FINE ] No + CAM:[NIKON ] [E4500 ] [FINE ] No + CAM:[NIKON ] [E5000 ] [FINE ] No + CAM:[NIKON ] [E5700 ] [FINE ] No + CAM:[NIKON ] [E775 ] [FINE ] No + CAM:[NIKON ] [E885 ] [FINE ] No + CAM:[OLYMPUS OPTICAL CO.,LTD ] [C3040Z ] [ ] No + CAM:[PENTAX ] [PENTAX Optio 550 ] [ ] No + CAM:[Research In Motion ] [BlackBerry 9530 ] [Superfine ] Yes + CAM:[SEIKO EPSON CORP. ] [PhotoPC 3000Z ] [ ] No + CAM:[SONY ] [DSC-H7 ] [ ] No + CAM:[SONY ] [DSC-H9 ] [ ] No + CAM:[SONY ] [DSC-S90 ] [ ] No + CAM:[SONY ] [DSC-W1 ] [ ] No + CAM:[SONY ] [SONY ] [ ] No + SW :[ACDSee ] [ ] + SW :[FixFoto ] [fine ] + SW :[IJG Library ] [090 ] + SW :[ZoomBrowser EX ] [high ] + + The following IJG-based editors also match this signature: + SW :[GIMP ] [090 ] + SW :[IrfanView ] [090 ] + SW :[idImager ] [090 ] + SW :[FastStone Image Viewer ] [090 ] + SW :[NeatImage ] [090 ] + SW :[Paint.NET ] [090 ] + SW :[Photomatix ] [090 ] + SW :[XnView ] [090 ] + + Based on the analysis of compression characteristics and EXIF metadata: + + ASSESSMENT: Class 1 - Image is processed/edited + + This may be a new software editor for the database. + If this file is processed, and editor doesn't appear in list above, + PLEASE ADD TO DATABASE with [Tools->Add Camera to DB] + + +*** Additional Info *** +NOTE: Data exists after EOF, range: 0x00000000-0x00012301 (74497 bytes)