Browse Source

refactor of Overlays

pull/908/head
Anton Firszov 7 years ago
parent
commit
9f0cce38ab
  1. 2
      src/ImageSharp/Color/Color.cs
  2. 2
      src/ImageSharp/Primitives/ValueSize.cs
  3. 45
      src/ImageSharp/Processing/BackgroundColorExtensions.cs
  4. 98
      src/ImageSharp/Processing/GlowExtensions.cs
  5. 4
      src/ImageSharp/Processing/Processors/Filters/LomographProcessor{TPixel}.cs
  6. 14
      src/ImageSharp/Processing/Processors/Filters/PolaroidProcessor{TPixel}.cs
  7. 86
      src/ImageSharp/Processing/Processors/Overlays/BackgroundColorProcessor.cs
  8. 101
      src/ImageSharp/Processing/Processors/Overlays/BackgroundColorProcessor{TPixel}.cs
  9. 125
      src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs
  10. 112
      src/ImageSharp/Processing/Processors/Overlays/GlowProcessor{TPixel}.cs
  11. 120
      src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor.cs
  12. 114
      src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor{TPixel}.cs
  13. 121
      src/ImageSharp/Processing/VignetteExtensions.cs
  14. 4
      tests/ImageSharp.Benchmarks/Samplers/Glow.cs
  15. 6
      tests/ImageSharp.Tests/Drawing/BeziersTests.cs
  16. 2
      tests/ImageSharp.Tests/Drawing/DrawImageTest.cs
  17. 8
      tests/ImageSharp.Tests/Drawing/DrawPathTests.cs
  18. 17
      tests/ImageSharp.Tests/Drawing/LineComplexPolygonTests.cs
  19. 33
      tests/ImageSharp.Tests/Drawing/LineTests.cs
  20. 9
      tests/ImageSharp.Tests/Drawing/PolygonTests.cs
  21. 16
      tests/ImageSharp.Tests/Drawing/SolidBezierTests.cs
  22. 9
      tests/ImageSharp.Tests/Drawing/SolidComplexPolygonTests.cs
  23. 25
      tests/ImageSharp.Tests/Drawing/SolidPolygonTests.cs
  24. 24
      tests/ImageSharp.Tests/Processing/Effects/BackgroundColorTest.cs
  25. 16
      tests/ImageSharp.Tests/Processing/Overlays/GlowTest.cs
  26. 18
      tests/ImageSharp.Tests/Processing/Overlays/VignetteTest.cs
  27. 4
      tests/ImageSharp.Tests/Processing/Processors/Effects/BackgroundColorTest.cs
  28. 6
      tests/ImageSharp.Tests/Processing/Processors/Overlays/GlowTest.cs
  29. 13
      tests/ImageSharp.Tests/Processing/Processors/Overlays/OverlayTestBase.cs
  30. 6
      tests/ImageSharp.Tests/Processing/Processors/Overlays/VignetteTest.cs

2
src/ImageSharp/Color/Color.cs

@ -86,6 +86,8 @@ namespace SixLabors.ImageSharp
public static Color FromRgba(byte r, byte g, byte b, byte a) => new Color(new Rgba32(r, g, b, a)); public static Color FromRgba(byte r, byte g, byte b, byte a) => new Color(new Rgba32(r, g, b, a));
public static Color FromRgb(byte r, byte g, byte b) => FromRgba(r, g, b, 255);
/// <summary> /// <summary>
/// Creates a new <see cref="Color"/> instance from the string representing a color in hexadecimal form. /// Creates a new <see cref="Color"/> instance from the string representing a color in hexadecimal form.
/// </summary> /// </summary>

2
src/ImageSharp/Primitives/ValueSize.cs

@ -7,7 +7,7 @@ using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Primitives namespace SixLabors.ImageSharp.Primitives
{ {
/// <summary> /// <summary>
/// Represents a value in relation to a value on the image /// Represents a value in relation to a value on the image.
/// </summary> /// </summary>
internal readonly struct ValueSize : IEquatable<ValueSize> internal readonly struct ValueSize : IEquatable<ValueSize>
{ {

45
src/ImageSharp/Processing/BackgroundColorExtensions.cs

@ -1,7 +1,6 @@
// Copyright (c) Six Labors and contributors. // Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing.Processors.Overlays; using SixLabors.ImageSharp.Processing.Processors.Overlays;
using SixLabors.Primitives; using SixLabors.Primitives;
@ -16,53 +15,55 @@ namespace SixLabors.ImageSharp.Processing
/// <summary> /// <summary>
/// Replaces the background color of image with the given one. /// Replaces the background color of image with the given one.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="source">The image this method extends.</param> /// <param name="source">The image this method extends.</param>
/// <param name="color">The color to set as the background.</param> /// <param name="color">The color to set as the background.</param>
/// <returns>The <see cref="Image{TPixel}"/>.</returns> /// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
public static IImageProcessingContext<TPixel> BackgroundColor<TPixel>(this IImageProcessingContext<TPixel> source, TPixel color) public static IImageProcessingContext BackgroundColor(this IImageProcessingContext source, Color color) =>
where TPixel : struct, IPixel<TPixel> BackgroundColor(source, GraphicsOptions.Default, color);
=> BackgroundColor(source, GraphicsOptions.Default, color);
/// <summary> /// <summary>
/// Replaces the background color of image with the given one. /// Replaces the background color of image with the given one.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="source">The image this method extends.</param> /// <param name="source">The image this method extends.</param>
/// <param name="color">The color to set as the background.</param> /// <param name="color">The color to set as the background.</param>
/// <param name="rectangle"> /// <param name="rectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter. /// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
/// </param> /// </param>
/// <returns>The <see cref="Image{TPixel}"/>.</returns> /// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
public static IImageProcessingContext<TPixel> BackgroundColor<TPixel>(this IImageProcessingContext<TPixel> source, TPixel color, Rectangle rectangle) public static IImageProcessingContext BackgroundColor(
where TPixel : struct, IPixel<TPixel> this IImageProcessingContext source,
=> BackgroundColor(source, GraphicsOptions.Default, color, rectangle); Color color,
Rectangle rectangle) =>
BackgroundColor(source, GraphicsOptions.Default, color, rectangle);
/// <summary> /// <summary>
/// Replaces the background color of image with the given one. /// Replaces the background color of image with the given one.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="source">The image this method extends.</param> /// <param name="source">The image this method extends.</param>
/// <param name="options">The options effecting pixel blending.</param> /// <param name="options">The options effecting pixel blending.</param>
/// <param name="color">The color to set as the background.</param> /// <param name="color">The color to set as the background.</param>
/// <returns>The <see cref="Image{TPixel}"/>.</returns> /// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
public static IImageProcessingContext<TPixel> BackgroundColor<TPixel>(this IImageProcessingContext<TPixel> source, GraphicsOptions options, TPixel color) public static IImageProcessingContext BackgroundColor(
where TPixel : struct, IPixel<TPixel> this IImageProcessingContext source,
=> source.ApplyProcessor(new BackgroundColorProcessor<TPixel>(color, options)); GraphicsOptions options,
Color color) =>
source.ApplyProcessor(new BackgroundColorProcessor(color, options));
/// <summary> /// <summary>
/// Replaces the background color of image with the given one. /// Replaces the background color of image with the given one.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="source">The image this method extends.</param> /// <param name="source">The image this method extends.</param>
/// <param name="options">The options effecting pixel blending.</param> /// <param name="options">The options effecting pixel blending.</param>
/// <param name="color">The color to set as the background.</param> /// <param name="color">The color to set as the background.</param>
/// <param name="rectangle"> /// <param name="rectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter. /// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
/// </param> /// </param>
/// <returns>The <see cref="Image{TPixel}"/>.</returns> /// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
public static IImageProcessingContext<TPixel> BackgroundColor<TPixel>(this IImageProcessingContext<TPixel> source, GraphicsOptions options, TPixel color, Rectangle rectangle) public static IImageProcessingContext BackgroundColor(
where TPixel : struct, IPixel<TPixel> this IImageProcessingContext source,
=> source.ApplyProcessor(new BackgroundColorProcessor<TPixel>(color, options), rectangle); GraphicsOptions options,
Color color,
Rectangle rectangle) =>
source.ApplyProcessor(new BackgroundColorProcessor(color, options), rectangle);
} }
} }

98
src/ImageSharp/Processing/GlowExtensions.cs

@ -1,7 +1,6 @@
// Copyright (c) Six Labors and contributors. // Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Primitives; using SixLabors.ImageSharp.Primitives;
using SixLabors.ImageSharp.Processing.Processors.Overlays; using SixLabors.ImageSharp.Processing.Processors.Overlays;
using SixLabors.Primitives; using SixLabors.Primitives;
@ -17,22 +16,18 @@ namespace SixLabors.ImageSharp.Processing
/// <summary> /// <summary>
/// Applies a radial glow effect to an image. /// Applies a radial glow effect to an image.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="source">The image this method extends.</param> /// <param name="source">The image this method extends.</param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns> /// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
public static IImageProcessingContext<TPixel> Glow<TPixel>(this IImageProcessingContext<TPixel> source) public static IImageProcessingContext Glow(this IImageProcessingContext source) =>
where TPixel : struct, IPixel<TPixel> Glow(source, GraphicsOptions.Default);
=> Glow(source, GraphicsOptions.Default);
/// <summary> /// <summary>
/// Applies a radial glow effect to an image. /// Applies a radial glow effect to an image.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="source">The image this method extends.</param> /// <param name="source">The image this method extends.</param>
/// <param name="color">The color to set as the glow.</param> /// <param name="color">The color to set as the glow.</param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns> /// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
public static IImageProcessingContext<TPixel> Glow<TPixel>(this IImageProcessingContext<TPixel> source, TPixel color) public static IImageProcessingContext Glow(this IImageProcessingContext source, Color color)
where TPixel : struct, IPixel<TPixel>
{ {
return Glow(source, GraphicsOptions.Default, color); return Glow(source, GraphicsOptions.Default, color);
} }
@ -40,31 +35,26 @@ namespace SixLabors.ImageSharp.Processing
/// <summary> /// <summary>
/// Applies a radial glow effect to an image. /// Applies a radial glow effect to an image.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="source">The image this method extends.</param> /// <param name="source">The image this method extends.</param>
/// <param name="radius">The the radius.</param> /// <param name="radius">The the radius.</param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns> /// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
public static IImageProcessingContext<TPixel> Glow<TPixel>(this IImageProcessingContext<TPixel> source, float radius) public static IImageProcessingContext Glow(this IImageProcessingContext source, float radius) =>
where TPixel : struct, IPixel<TPixel> Glow(source, GraphicsOptions.Default, radius);
=> Glow(source, GraphicsOptions.Default, radius);
/// <summary> /// <summary>
/// Applies a radial glow effect to an image. /// Applies a radial glow effect to an image.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="source">The image this method extends.</param> /// <param name="source">The image this method extends.</param>
/// <param name="rectangle"> /// <param name="rectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter. /// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
/// </param> /// </param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns> /// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
public static IImageProcessingContext<TPixel> Glow<TPixel>(this IImageProcessingContext<TPixel> source, Rectangle rectangle) public static IImageProcessingContext Glow(this IImageProcessingContext source, Rectangle rectangle) =>
where TPixel : struct, IPixel<TPixel> source.Glow(GraphicsOptions.Default, rectangle);
=> source.Glow(GraphicsOptions.Default, rectangle);
/// <summary> /// <summary>
/// Applies a radial glow effect to an image. /// Applies a radial glow effect to an image.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="source">The image this method extends.</param> /// <param name="source">The image this method extends.</param>
/// <param name="color">The color to set as the glow.</param> /// <param name="color">The color to set as the glow.</param>
/// <param name="radius">The the radius.</param> /// <param name="radius">The the radius.</param>
@ -72,63 +62,66 @@ namespace SixLabors.ImageSharp.Processing
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter. /// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
/// </param> /// </param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns> /// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
public static IImageProcessingContext<TPixel> Glow<TPixel>(this IImageProcessingContext<TPixel> source, TPixel color, float radius, Rectangle rectangle) public static IImageProcessingContext Glow(
where TPixel : struct, IPixel<TPixel> this IImageProcessingContext source,
=> source.Glow(GraphicsOptions.Default, color, ValueSize.Absolute(radius), rectangle); Color color,
float radius,
Rectangle rectangle) =>
source.Glow(GraphicsOptions.Default, color, ValueSize.Absolute(radius), rectangle);
/// <summary> /// <summary>
/// Applies a radial glow effect to an image. /// Applies a radial glow effect to an image.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="source">The image this method extends.</param> /// <param name="source">The image this method extends.</param>
/// <param name="options">The options effecting things like blending.</param> /// <param name="options">The options effecting things like blending.</param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns> /// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
public static IImageProcessingContext<TPixel> Glow<TPixel>(this IImageProcessingContext<TPixel> source, GraphicsOptions options) public static IImageProcessingContext Glow(this IImageProcessingContext source, GraphicsOptions options) =>
where TPixel : struct, IPixel<TPixel> source.Glow(options, Color.Black, ValueSize.PercentageOfWidth(0.5f));
=> source.Glow(options, NamedColors<TPixel>.Black, ValueSize.PercentageOfWidth(0.5f));
/// <summary> /// <summary>
/// Applies a radial glow effect to an image. /// Applies a radial glow effect to an image.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="source">The image this method extends.</param> /// <param name="source">The image this method extends.</param>
/// <param name="options">The options effecting things like blending.</param> /// <param name="options">The options effecting things like blending.</param>
/// <param name="color">The color to set as the glow.</param> /// <param name="color">The color to set as the glow.</param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns> /// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
public static IImageProcessingContext<TPixel> Glow<TPixel>(this IImageProcessingContext<TPixel> source, GraphicsOptions options, TPixel color) public static IImageProcessingContext Glow(
where TPixel : struct, IPixel<TPixel> this IImageProcessingContext source,
=> source.Glow(options, color, ValueSize.PercentageOfWidth(0.5f)); GraphicsOptions options,
Color color) =>
source.Glow(options, color, ValueSize.PercentageOfWidth(0.5f));
/// <summary> /// <summary>
/// Applies a radial glow effect to an image. /// Applies a radial glow effect to an image.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="source">The image this method extends.</param> /// <param name="source">The image this method extends.</param>
/// <param name="options">The options effecting things like blending.</param> /// <param name="options">The options effecting things like blending.</param>
/// <param name="radius">The the radius.</param> /// <param name="radius">The the radius.</param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns> /// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
public static IImageProcessingContext<TPixel> Glow<TPixel>(this IImageProcessingContext<TPixel> source, GraphicsOptions options, float radius) public static IImageProcessingContext Glow(
where TPixel : struct, IPixel<TPixel> this IImageProcessingContext source,
=> source.Glow(options, NamedColors<TPixel>.Black, ValueSize.Absolute(radius)); GraphicsOptions options,
float radius) =>
source.Glow(options, Color.Black, ValueSize.Absolute(radius));
/// <summary> /// <summary>
/// Applies a radial glow effect to an image. /// Applies a radial glow effect to an image.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="source">The image this method extends.</param> /// <param name="source">The image this method extends.</param>
/// <param name="options">The options effecting things like blending.</param> /// <param name="options">The options effecting things like blending.</param>
/// <param name="rectangle"> /// <param name="rectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter. /// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
/// </param> /// </param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns> /// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
public static IImageProcessingContext<TPixel> Glow<TPixel>(this IImageProcessingContext<TPixel> source, GraphicsOptions options, Rectangle rectangle) public static IImageProcessingContext Glow(
where TPixel : struct, IPixel<TPixel> this IImageProcessingContext source,
=> source.Glow(options, NamedColors<TPixel>.Black, ValueSize.PercentageOfWidth(0.5f), rectangle); GraphicsOptions options,
Rectangle rectangle) =>
source.Glow(options, Color.Black, ValueSize.PercentageOfWidth(0.5f), rectangle);
/// <summary> /// <summary>
/// Applies a radial glow effect to an image. /// Applies a radial glow effect to an image.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="source">The image this method extends.</param> /// <param name="source">The image this method extends.</param>
/// <param name="options">The options effecting things like blending.</param> /// <param name="options">The options effecting things like blending.</param>
/// <param name="color">The color to set as the glow.</param> /// <param name="color">The color to set as the glow.</param>
@ -137,14 +130,17 @@ namespace SixLabors.ImageSharp.Processing
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter. /// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
/// </param> /// </param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns> /// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
public static IImageProcessingContext<TPixel> Glow<TPixel>(this IImageProcessingContext<TPixel> source, GraphicsOptions options, TPixel color, float radius, Rectangle rectangle) public static IImageProcessingContext Glow(
where TPixel : struct, IPixel<TPixel> this IImageProcessingContext source,
=> source.Glow(options, color, ValueSize.Absolute(radius), rectangle); GraphicsOptions options,
Color color,
float radius,
Rectangle rectangle) =>
source.Glow(options, color, ValueSize.Absolute(radius), rectangle);
/// <summary> /// <summary>
/// Applies a radial glow effect to an image. /// Applies a radial glow effect to an image.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="source">The image this method extends.</param> /// <param name="source">The image this method extends.</param>
/// <param name="options">The options effecting things like blending.</param> /// <param name="options">The options effecting things like blending.</param>
/// <param name="color">The color to set as the glow.</param> /// <param name="color">The color to set as the glow.</param>
@ -153,21 +149,27 @@ namespace SixLabors.ImageSharp.Processing
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter. /// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
/// </param> /// </param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns> /// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
private static IImageProcessingContext<TPixel> Glow<TPixel>(this IImageProcessingContext<TPixel> source, GraphicsOptions options, TPixel color, ValueSize radius, Rectangle rectangle) private static IImageProcessingContext Glow(
where TPixel : struct, IPixel<TPixel> this IImageProcessingContext source,
=> source.ApplyProcessor(new GlowProcessor<TPixel>(color, radius, options), rectangle); GraphicsOptions options,
Color color,
ValueSize radius,
Rectangle rectangle) =>
source.ApplyProcessor(new GlowProcessor(color, radius, options), rectangle);
/// <summary> /// <summary>
/// Applies a radial glow effect to an image. /// Applies a radial glow effect to an image.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="source">The image this method extends.</param> /// <param name="source">The image this method extends.</param>
/// <param name="options">The options effecting things like blending.</param> /// <param name="options">The options effecting things like blending.</param>
/// <param name="color">The color to set as the glow.</param> /// <param name="color">The color to set as the glow.</param>
/// <param name="radius">The the radius.</param> /// <param name="radius">The the radius.</param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns> /// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
private static IImageProcessingContext<TPixel> Glow<TPixel>(this IImageProcessingContext<TPixel> source, GraphicsOptions options, TPixel color, ValueSize radius) private static IImageProcessingContext Glow(
where TPixel : struct, IPixel<TPixel> this IImageProcessingContext source,
=> source.ApplyProcessor(new GlowProcessor<TPixel>(color, radius, options)); GraphicsOptions options,
Color color,
ValueSize radius) =>
source.ApplyProcessor(new GlowProcessor(color, radius, options));
} }
} }

4
src/ImageSharp/Processing/Processors/Filters/LomographProcessor{TPixel}.cs

@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters
internal class LomographProcessor<TPixel> : FilterProcessor<TPixel> internal class LomographProcessor<TPixel> : FilterProcessor<TPixel>
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
private static readonly TPixel VeryDarkGreen = ColorBuilder<TPixel>.FromRGBA(0, 10, 0, 255); private static readonly Color VeryDarkGreen = Color.FromRgba(0, 10, 0, 255);
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="LomographProcessor{TPixel}"/> class. /// Initializes a new instance of the <see cref="LomographProcessor{TPixel}"/> class.
@ -27,7 +27,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters
/// <inheritdoc/> /// <inheritdoc/>
protected override void AfterFrameApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration) protected override void AfterFrameApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{ {
new VignetteProcessor<TPixel>(VeryDarkGreen).Apply(source, sourceRectangle, configuration); new VignetteProcessor(VeryDarkGreen).Apply(source, sourceRectangle, configuration);
} }
} }
} }

14
src/ImageSharp/Processing/Processors/Filters/PolaroidProcessor{TPixel}.cs

@ -13,8 +13,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters
internal class PolaroidProcessor<TPixel> : FilterProcessor<TPixel> internal class PolaroidProcessor<TPixel> : FilterProcessor<TPixel>
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
private static readonly TPixel VeryDarkOrange = ColorBuilder<TPixel>.FromRGB(102, 34, 0); private static readonly Color LightOrange = Color.FromRgba(255, 153, 102, 128);
private static readonly TPixel LightOrange = ColorBuilder<TPixel>.FromRGBA(255, 153, 102, 128);
private static readonly Color VeryDarkOrange = Color.FromRgb(102, 34, 0);
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="PolaroidProcessor{TPixel}"/> class. /// Initializes a new instance of the <see cref="PolaroidProcessor{TPixel}"/> class.
@ -26,10 +27,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters
} }
/// <inheritdoc/> /// <inheritdoc/>
protected override void AfterFrameApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration) protected override void AfterFrameApply(
ImageFrame<TPixel> source,
Rectangle sourceRectangle,
Configuration configuration)
{ {
new VignetteProcessor<TPixel>(VeryDarkOrange).Apply(source, sourceRectangle, configuration); new VignetteProcessor(VeryDarkOrange).Apply(source, sourceRectangle, configuration);
new GlowProcessor<TPixel>(LightOrange, source.Width / 4F).Apply(source, sourceRectangle, configuration); new GlowProcessor(LightOrange, source.Width / 4F).Apply(source, sourceRectangle, configuration);
} }
} }
} }

86
src/ImageSharp/Processing/Processors/Overlays/BackgroundColorProcessor.cs

@ -1,31 +1,21 @@
// Copyright (c) Six Labors and contributors. // Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.ParallelUtils;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Processing.Processors.Overlays namespace SixLabors.ImageSharp.Processing.Processors.Overlays
{ {
/// <summary> /// <summary>
/// Sets the background color of the image. /// Defines a processing operation to replace the background color of an <see cref="Image"/>.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam> public sealed class BackgroundColorProcessor : IImageProcessor
internal class BackgroundColorProcessor<TPixel> : ImageProcessor<TPixel>
where TPixel : struct, IPixel<TPixel>
{ {
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="BackgroundColorProcessor{TPixel}"/> class. /// Initializes a new instance of the <see cref="BackgroundColorProcessor"/> class.
/// </summary> /// </summary>
/// <param name="color">The <typeparamref name="TPixel"/> to set the background color to.</param> /// <param name="color">The <see cref="Color"/> to set the background color to.</param>
/// <param name="options">The options defining blending algorithm and amount.</param> /// <param name="options">The options defining blending algorithm and amount.</param>
public BackgroundColorProcessor(TPixel color, GraphicsOptions options) public BackgroundColorProcessor(Color color, GraphicsOptions options)
{ {
this.Color = color; this.Color = color;
this.GraphicsOptions = options; this.GraphicsOptions = options;
@ -39,69 +29,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
/// <summary> /// <summary>
/// Gets the background color value. /// Gets the background color value.
/// </summary> /// </summary>
public TPixel Color { get; } public Color Color { get; }
/// <inheritdoc/> /// <inheritdoc />
protected override void OnFrameApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration) public IImageProcessor<TPixel> CreatePixelSpecificProcessor<TPixel>()
where TPixel : struct, IPixel<TPixel>
{ {
int startY = sourceRectangle.Y; return new BackgroundColorProcessor<TPixel>(this);
int endY = sourceRectangle.Bottom;
int startX = sourceRectangle.X;
int endX = sourceRectangle.Right;
// Align start/end positions.
int minX = Math.Max(0, startX);
int maxX = Math.Min(source.Width, endX);
int minY = Math.Max(0, startY);
int maxY = Math.Min(source.Height, endY);
// Reset offset if necessary.
if (minX > 0)
{
startX = 0;
}
if (minY > 0)
{
startY = 0;
}
int width = maxX - minX;
var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY);
using (IMemoryOwner<TPixel> colors = source.MemoryAllocator.Allocate<TPixel>(width))
using (IMemoryOwner<float> amount = source.MemoryAllocator.Allocate<float>(width))
{
// Be careful! Do not capture colorSpan & amountSpan in the lambda below!
Span<TPixel> colorSpan = colors.GetSpan();
Span<float> amountSpan = amount.GetSpan();
colorSpan.Fill(this.Color);
amountSpan.Fill(this.GraphicsOptions.BlendPercentage);
PixelBlender<TPixel> blender = PixelOperations<TPixel>.Instance.GetPixelBlender(this.GraphicsOptions);
ParallelHelper.IterateRows(
workingRect,
configuration,
rows =>
{
for (int y = rows.Min; y < rows.Max; y++)
{
Span<TPixel> destination =
source.GetPixelRowSpan(y - startY).Slice(minX - startX, width);
// This switched color & destination in the 2nd and 3rd places because we are applying the target color under the current one
blender.Blend(
source.Configuration,
destination,
colors.GetSpan(),
destination,
amount.GetSpan());
}
});
}
} }
} }
} }

101
src/ImageSharp/Processing/Processors/Overlays/BackgroundColorProcessor{TPixel}.cs

@ -0,0 +1,101 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.ParallelUtils;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Processing.Processors.Overlays
{
/// <summary>
/// Sets the background color of the image.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
internal class BackgroundColorProcessor<TPixel> : ImageProcessor<TPixel>
where TPixel : struct, IPixel<TPixel>
{
private readonly BackgroundColorProcessor definition;
/// <summary>
/// Initializes a new instance of the <see cref="BackgroundColorProcessor{TPixel}"/> class.
/// </summary>
public BackgroundColorProcessor(BackgroundColorProcessor definition)
{
this.definition = definition;
}
/// <inheritdoc/>
protected override void OnFrameApply(
ImageFrame<TPixel> source,
Rectangle sourceRectangle,
Configuration configuration)
{
TPixel color = this.definition.Color.ToPixel<TPixel>();
GraphicsOptions graphicsOptions = this.definition.GraphicsOptions;
int startY = sourceRectangle.Y;
int endY = sourceRectangle.Bottom;
int startX = sourceRectangle.X;
int endX = sourceRectangle.Right;
// Align start/end positions.
int minX = Math.Max(0, startX);
int maxX = Math.Min(source.Width, endX);
int minY = Math.Max(0, startY);
int maxY = Math.Min(source.Height, endY);
// Reset offset if necessary.
if (minX > 0)
{
startX = 0;
}
if (minY > 0)
{
startY = 0;
}
int width = maxX - minX;
var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY);
using (IMemoryOwner<TPixel> colors = source.MemoryAllocator.Allocate<TPixel>(width))
using (IMemoryOwner<float> amount = source.MemoryAllocator.Allocate<float>(width))
{
// Be careful! Do not capture colorSpan & amountSpan in the lambda below!
Span<TPixel> colorSpan = colors.GetSpan();
Span<float> amountSpan = amount.GetSpan();
colorSpan.Fill(color);
amountSpan.Fill(graphicsOptions.BlendPercentage);
PixelBlender<TPixel> blender = PixelOperations<TPixel>.Instance.GetPixelBlender(graphicsOptions);
ParallelHelper.IterateRows(
workingRect,
configuration,
rows =>
{
for (int y = rows.Min; y < rows.Max; y++)
{
Span<TPixel> destination =
source.GetPixelRowSpan(y - startY).Slice(minX - startX, width);
// This switched color & destination in the 2nd and 3rd places because we are applying the target color under the current one
blender.Blend(
source.Configuration,
destination,
colors.GetSpan(),
destination,
amount.GetSpan());
}
});
}
}
}
}

125
src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs

@ -1,69 +1,56 @@
// Copyright (c) Six Labors and contributors. // Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using System.Numerics;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.ParallelUtils;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Primitives; using SixLabors.ImageSharp.Primitives;
using SixLabors.Memory;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Processing.Processors.Overlays namespace SixLabors.ImageSharp.Processing.Processors.Overlays
{ {
/// <summary> /// <summary>
/// An <see cref="IImageProcessor{TPixel}"/> that applies a radial glow effect an <see cref="Image{TPixel}"/>. /// Defines a radial glow effect applicable to an <see cref="Image"/>.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam> public sealed class GlowProcessor : IImageProcessor
internal class GlowProcessor<TPixel> : ImageProcessor<TPixel>
where TPixel : struct, IPixel<TPixel>
{ {
private readonly PixelBlender<TPixel> blender;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="GlowProcessor{TPixel}" /> class. /// Initializes a new instance of the <see cref="GlowProcessor" /> class.
/// </summary> /// </summary>
/// <param name="color">The color or the glow.</param> /// <param name="color">The color or the glow.</param>
public GlowProcessor(TPixel color) public GlowProcessor(Color color)
: this(color, 0) : this(color, 0)
{ {
} }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="GlowProcessor{TPixel}" /> class. /// Initializes a new instance of the <see cref="GlowProcessor" /> class.
/// </summary> /// </summary>
/// <param name="color">The color or the glow.</param> /// <param name="color">The color or the glow.</param>
/// <param name="radius">The radius of the glow.</param> /// <param name="options">The options effecting blending and composition.</param>
public GlowProcessor(TPixel color, ValueSize radius) public GlowProcessor(Color color, GraphicsOptions options)
: this(color, radius, GraphicsOptions.Default) : this(color, 0, options)
{ {
} }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="GlowProcessor{TPixel}" /> class. /// Initializes a new instance of the <see cref="GlowProcessor" /> class.
/// </summary> /// </summary>
/// <param name="color">The color or the glow.</param> /// <param name="color">The color or the glow.</param>
/// <param name="options">The options effecting blending and composition.</param> /// <param name="radius">The radius of the glow.</param>
public GlowProcessor(TPixel color, GraphicsOptions options) internal GlowProcessor(Color color, ValueSize radius)
: this(color, 0, options) : this(color, radius, GraphicsOptions.Default)
{ {
} }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="GlowProcessor{TPixel}" /> class. /// Initializes a new instance of the <see cref="GlowProcessor" /> class.
/// </summary> /// </summary>
/// <param name="color">The color or the glow.</param> /// <param name="color">The color or the glow.</param>
/// <param name="radius">The radius of the glow.</param> /// <param name="radius">The radius of the glow.</param>
/// <param name="options">The options effecting blending and composition.</param> /// <param name="options">The options effecting blending and composition.</param>
public GlowProcessor(TPixel color, ValueSize radius, GraphicsOptions options) internal GlowProcessor(Color color, ValueSize radius, GraphicsOptions options)
{ {
this.GlowColor = color; this.GlowColor = color;
this.Radius = radius; this.Radius = radius;
this.blender = PixelOperations<TPixel>.Instance.GetPixelBlender(options);
this.GraphicsOptions = options; this.GraphicsOptions = options;
} }
@ -73,86 +60,20 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
public GraphicsOptions GraphicsOptions { get; } public GraphicsOptions GraphicsOptions { get; }
/// <summary> /// <summary>
/// Gets or sets the glow color to apply. /// Gets the glow color to apply.
/// </summary> /// </summary>
public TPixel GlowColor { get; set; } public Color GlowColor { get; }
/// <summary> /// <summary>
/// Gets or sets the the radius. /// Gets the the radius.
/// </summary> /// </summary>
public ValueSize Radius { get; set; } internal ValueSize Radius { get; }
/// <inheritdoc/> /// <inheritdoc />
protected override void OnFrameApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration) public IImageProcessor<TPixel> CreatePixelSpecificProcessor<TPixel>()
where TPixel : struct, IPixel<TPixel>
{ {
// TODO: can we simplify the rectangle calculation? return new GlowProcessor<TPixel>(this);
int startY = sourceRectangle.Y;
int endY = sourceRectangle.Bottom;
int startX = sourceRectangle.X;
int endX = sourceRectangle.Right;
TPixel glowColor = this.GlowColor;
Vector2 center = Rectangle.Center(sourceRectangle);
float finalRadius = this.Radius.Calculate(source.Size());
float maxDistance = finalRadius > 0 ? MathF.Min(finalRadius, sourceRectangle.Width * .5F) : sourceRectangle.Width * .5F;
// Align start/end positions.
int minX = Math.Max(0, startX);
int maxX = Math.Min(source.Width, endX);
int minY = Math.Max(0, startY);
int maxY = Math.Min(source.Height, endY);
// Reset offset if necessary.
if (minX > 0)
{
startX = 0;
}
if (minY > 0)
{
startY = 0;
}
int width = maxX - minX;
int offsetX = minX - startX;
var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY);
using (IMemoryOwner<TPixel> rowColors = source.MemoryAllocator.Allocate<TPixel>(width))
{
rowColors.GetSpan().Fill(glowColor);
ParallelHelper.IterateRowsWithTempBuffer<float>(
workingRect,
configuration,
(rows, amounts) =>
{
Span<float> amountsSpan = amounts.Span;
for (int y = rows.Min; y < rows.Max; y++)
{
int offsetY = y - startY;
for (int i = 0; i < width; i++)
{
float distance = Vector2.Distance(center, new Vector2(i + offsetX, offsetY));
amountsSpan[i] =
(this.GraphicsOptions.BlendPercentage * (1 - (.95F * (distance / maxDistance))))
.Clamp(0, 1);
}
Span<TPixel> destination = source.GetPixelRowSpan(offsetY).Slice(offsetX, width);
this.blender.Blend(
source.Configuration,
destination,
destination,
rowColors.GetSpan(),
amountsSpan);
}
});
}
} }
} }
} }

112
src/ImageSharp/Processing/Processors/Overlays/GlowProcessor{TPixel}.cs

@ -0,0 +1,112 @@
// 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.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.ParallelUtils;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Processing.Processors.Overlays
{
/// <summary>
/// An <see cref="IImageProcessor{TPixel}"/> that applies a radial glow effect an <see cref="Image{TPixel}"/>.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
internal class GlowProcessor<TPixel> : ImageProcessor<TPixel>
where TPixel : struct, IPixel<TPixel>
{
private readonly PixelBlender<TPixel> blender;
private readonly GlowProcessor definition;
public GlowProcessor(GlowProcessor definition)
{
this.definition = definition;
this.blender = PixelOperations<TPixel>.Instance.GetPixelBlender(definition.GraphicsOptions);
}
/// <inheritdoc/>
protected override void OnFrameApply(
ImageFrame<TPixel> source,
Rectangle sourceRectangle,
Configuration configuration)
{
// TODO: can we simplify the rectangle calculation?
int startY = sourceRectangle.Y;
int endY = sourceRectangle.Bottom;
int startX = sourceRectangle.X;
int endX = sourceRectangle.Right;
TPixel glowColor = this.definition.GlowColor.ToPixel<TPixel>();
Vector2 center = Rectangle.Center(sourceRectangle);
float finalRadius = this.definition.Radius.Calculate(source.Size());
float maxDistance = finalRadius > 0
? MathF.Min(finalRadius, sourceRectangle.Width * .5F)
: sourceRectangle.Width * .5F;
// Align start/end positions.
int minX = Math.Max(0, startX);
int maxX = Math.Min(source.Width, endX);
int minY = Math.Max(0, startY);
int maxY = Math.Min(source.Height, endY);
// Reset offset if necessary.
if (minX > 0)
{
startX = 0;
}
if (minY > 0)
{
startY = 0;
}
int width = maxX - minX;
int offsetX = minX - startX;
var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY);
float blendPercentage = this.definition.GraphicsOptions.BlendPercentage;
using (IMemoryOwner<TPixel> rowColors = source.MemoryAllocator.Allocate<TPixel>(width))
{
rowColors.GetSpan().Fill(glowColor);
ParallelHelper.IterateRowsWithTempBuffer<float>(
workingRect,
configuration,
(rows, amounts) =>
{
Span<float> amountsSpan = amounts.Span;
for (int y = rows.Min; y < rows.Max; y++)
{
int offsetY = y - startY;
for (int i = 0; i < width; i++)
{
float distance = Vector2.Distance(center, new Vector2(i + offsetX, offsetY));
amountsSpan[i] =
(blendPercentage * (1 - (.95F * (distance / maxDistance)))).Clamp(0, 1);
}
Span<TPixel> destination = source.GetPixelRowSpan(offsetY).Slice(offsetX, width);
this.blender.Blend(
source.Configuration,
destination,
destination,
rowColors.GetSpan(),
amountsSpan);
}
});
}
}
}
}

120
src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor.cs

@ -1,63 +1,48 @@
// Copyright (c) Six Labors and contributors. // Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using System.Numerics;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.ParallelUtils;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Primitives; using SixLabors.ImageSharp.Primitives;
using SixLabors.Memory;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Processing.Processors.Overlays namespace SixLabors.ImageSharp.Processing.Processors.Overlays
{ {
/// <summary> /// <summary>
/// An <see cref="IImageProcessor{TPixel}"/> that applies a radial vignette effect to an <see cref="Image{TPixel}"/>. /// Defines a radial vignette effect applicable to an <see cref="Image"/>.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam> public sealed class VignetteProcessor : IImageProcessor
internal class VignetteProcessor<TPixel> : ImageProcessor<TPixel>
where TPixel : struct, IPixel<TPixel>
{ {
private readonly PixelBlender<TPixel> blender;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="VignetteProcessor{TPixel}" /> class. /// Initializes a new instance of the <see cref="VignetteProcessor" /> class.
/// </summary> /// </summary>
/// <param name="color">The color of the vignette.</param> /// <param name="color">The color of the vignette.</param>
public VignetteProcessor(TPixel color) public VignetteProcessor(Color color)
: this(color, GraphicsOptions.Default) : this(color, GraphicsOptions.Default)
{ {
} }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="VignetteProcessor{TPixel}" /> class. /// Initializes a new instance of the <see cref="VignetteProcessor" /> class.
/// </summary> /// </summary>
/// <param name="color">The color of the vignette.</param> /// <param name="color">The color of the vignette.</param>
/// <param name="options">The options effecting blending and composition.</param> /// <param name="options">The options effecting blending and composition.</param>
public VignetteProcessor(TPixel color, GraphicsOptions options) public VignetteProcessor(Color color, GraphicsOptions options)
{ {
this.VignetteColor = color; this.VignetteColor = color;
this.GraphicsOptions = options; this.GraphicsOptions = options;
this.blender = PixelOperations<TPixel>.Instance.GetPixelBlender(options);
} }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="VignetteProcessor{TPixel}" /> class. /// Initializes a new instance of the <see cref="VignetteProcessor" /> class.
/// </summary> /// </summary>
/// <param name="color">The color of the vignette.</param> /// <param name="color">The color of the vignette.</param>
/// <param name="radiusX">The x-radius.</param> /// <param name="radiusX">The x-radius.</param>
/// <param name="radiusY">The y-radius.</param> /// <param name="radiusY">The y-radius.</param>
/// <param name="options">The options effecting blending and composition.</param> /// <param name="options">The options effecting blending and composition.</param>
public VignetteProcessor(TPixel color, ValueSize radiusX, ValueSize radiusY, GraphicsOptions options) internal VignetteProcessor(Color color, ValueSize radiusX, ValueSize radiusY, GraphicsOptions options)
{ {
this.VignetteColor = color; this.VignetteColor = color;
this.RadiusX = radiusX; this.RadiusX = radiusX;
this.RadiusY = radiusY; this.RadiusY = radiusY;
this.blender = PixelOperations<TPixel>.Instance.GetPixelBlender(options);
this.GraphicsOptions = options; this.GraphicsOptions = options;
} }
@ -67,94 +52,25 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
public GraphicsOptions GraphicsOptions { get; } public GraphicsOptions GraphicsOptions { get; }
/// <summary> /// <summary>
/// Gets or sets the vignette color to apply. /// Gets the vignette color to apply.
/// </summary> /// </summary>
public TPixel VignetteColor { get; set; } public Color VignetteColor { get; }
/// <summary> /// <summary>
/// Gets or sets the the x-radius. /// Gets the the x-radius.
/// </summary> /// </summary>
public ValueSize RadiusX { get; set; } internal ValueSize RadiusX { get; }
/// <summary> /// <summary>
/// Gets or sets the the y-radius. /// Gets the the y-radius.
/// </summary> /// </summary>
public ValueSize RadiusY { get; set; } internal ValueSize RadiusY { get; }
/// <inheritdoc/> /// <inheritdoc />
protected override void OnFrameApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration) public IImageProcessor<TPixel> CreatePixelSpecificProcessor<TPixel>()
where TPixel : struct, IPixel<TPixel>
{ {
int startY = sourceRectangle.Y; return new VignetteProcessor<TPixel>(this);
int endY = sourceRectangle.Bottom;
int startX = sourceRectangle.X;
int endX = sourceRectangle.Right;
TPixel vignetteColor = this.VignetteColor;
Vector2 centre = Rectangle.Center(sourceRectangle);
Size sourceSize = source.Size();
float finalRadiusX = this.RadiusX.Calculate(sourceSize);
float finalRadiusY = this.RadiusY.Calculate(sourceSize);
float rX = finalRadiusX > 0 ? MathF.Min(finalRadiusX, sourceRectangle.Width * .5F) : sourceRectangle.Width * .5F;
float rY = finalRadiusY > 0 ? MathF.Min(finalRadiusY, sourceRectangle.Height * .5F) : sourceRectangle.Height * .5F;
float maxDistance = MathF.Sqrt((rX * rX) + (rY * rY));
// Align start/end positions.
int minX = Math.Max(0, startX);
int maxX = Math.Min(source.Width, endX);
int minY = Math.Max(0, startY);
int maxY = Math.Min(source.Height, endY);
// Reset offset if necessary.
if (minX > 0)
{
startX = 0;
}
if (minY > 0)
{
startY = 0;
}
int width = maxX - minX;
int offsetX = minX - startX;
var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY);
using (IMemoryOwner<TPixel> rowColors = source.MemoryAllocator.Allocate<TPixel>(width))
{
rowColors.GetSpan().Fill(vignetteColor);
ParallelHelper.IterateRowsWithTempBuffer<float>(
workingRect,
configuration,
(rows, amounts) =>
{
Span<float> amountsSpan = amounts.Span;
for (int y = rows.Min; y < rows.Max; y++)
{
int offsetY = y - startY;
for (int i = 0; i < width; i++)
{
float distance = Vector2.Distance(centre, new Vector2(i + offsetX, offsetY));
amountsSpan[i] =
(this.GraphicsOptions.BlendPercentage * (.9F * (distance / maxDistance))).Clamp(
0,
1);
}
Span<TPixel> destination = source.GetPixelRowSpan(offsetY).Slice(offsetX, width);
this.blender.Blend(
source.Configuration,
destination,
destination,
rowColors.GetSpan(),
amountsSpan);
}
});
}
} }
} }
} }

114
src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor{TPixel}.cs

@ -0,0 +1,114 @@
// 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.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.ParallelUtils;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Processing.Processors.Overlays
{
/// <summary>
/// An <see cref="IImageProcessor{TPixel}"/> that applies a radial vignette effect to an <see cref="Image{TPixel}"/>.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
internal class VignetteProcessor<TPixel> : ImageProcessor<TPixel>
where TPixel : struct, IPixel<TPixel>
{
private readonly PixelBlender<TPixel> blender;
private readonly VignetteProcessor definition;
public VignetteProcessor(VignetteProcessor definition)
{
this.definition = definition;
this.blender = PixelOperations<TPixel>.Instance.GetPixelBlender(definition.GraphicsOptions);
}
/// <inheritdoc/>
protected override void OnFrameApply(
ImageFrame<TPixel> source,
Rectangle sourceRectangle,
Configuration configuration)
{
int startY = sourceRectangle.Y;
int endY = sourceRectangle.Bottom;
int startX = sourceRectangle.X;
int endX = sourceRectangle.Right;
TPixel vignetteColor = this.definition.VignetteColor.ToPixel<TPixel>();
Vector2 centre = Rectangle.Center(sourceRectangle);
Size sourceSize = source.Size();
float finalRadiusX = this.definition.RadiusX.Calculate(sourceSize);
float finalRadiusY = this.definition.RadiusY.Calculate(sourceSize);
float rX = finalRadiusX > 0
? MathF.Min(finalRadiusX, sourceRectangle.Width * .5F)
: sourceRectangle.Width * .5F;
float rY = finalRadiusY > 0
? MathF.Min(finalRadiusY, sourceRectangle.Height * .5F)
: sourceRectangle.Height * .5F;
float maxDistance = MathF.Sqrt((rX * rX) + (rY * rY));
// Align start/end positions.
int minX = Math.Max(0, startX);
int maxX = Math.Min(source.Width, endX);
int minY = Math.Max(0, startY);
int maxY = Math.Min(source.Height, endY);
// Reset offset if necessary.
if (minX > 0)
{
startX = 0;
}
if (minY > 0)
{
startY = 0;
}
int width = maxX - minX;
int offsetX = minX - startX;
var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY);
float blendPercentage = this.definition.GraphicsOptions.BlendPercentage;
using (IMemoryOwner<TPixel> rowColors = source.MemoryAllocator.Allocate<TPixel>(width))
{
rowColors.GetSpan().Fill(vignetteColor);
ParallelHelper.IterateRowsWithTempBuffer<float>(
workingRect,
configuration,
(rows, amounts) =>
{
Span<float> amountsSpan = amounts.Span;
for (int y = rows.Min; y < rows.Max; y++)
{
int offsetY = y - startY;
for (int i = 0; i < width; i++)
{
float distance = Vector2.Distance(centre, new Vector2(i + offsetX, offsetY));
amountsSpan[i] = (blendPercentage * (.9F * (distance / maxDistance))).Clamp(0, 1);
}
Span<TPixel> destination = source.GetPixelRowSpan(offsetY).Slice(offsetX, width);
this.blender.Blend(
source.Configuration,
destination,
destination,
rowColors.GetSpan(),
amountsSpan);
}
});
}
}
}
}

121
src/ImageSharp/Processing/VignetteExtensions.cs

@ -1,7 +1,6 @@
// Copyright (c) Six Labors and contributors. // Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Primitives; using SixLabors.ImageSharp.Primitives;
using SixLabors.ImageSharp.Processing.Processors.Overlays; using SixLabors.ImageSharp.Processing.Processors.Overlays;
using SixLabors.Primitives; using SixLabors.Primitives;
@ -9,7 +8,7 @@ using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Processing namespace SixLabors.ImageSharp.Processing
{ {
/// <summary> /// <summary>
/// Defines extensions that allow the application of a radial glow to an <see cref="Image{TPixel}"/> /// Defines extensions that allow the application of a radial glow to an <see cref="Image"/>
/// using Mutate/Clone. /// using Mutate/Clone.
/// </summary> /// </summary>
public static class VignetteExtensions public static class VignetteExtensions
@ -17,53 +16,47 @@ namespace SixLabors.ImageSharp.Processing
/// <summary> /// <summary>
/// Applies a radial vignette effect to an image. /// Applies a radial vignette effect to an image.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="source">The image this method extends.</param> /// <param name="source">The image this method extends.</param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns> /// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
public static IImageProcessingContext<TPixel> Vignette<TPixel>(this IImageProcessingContext<TPixel> source) public static IImageProcessingContext Vignette(this IImageProcessingContext source) =>
where TPixel : struct, IPixel<TPixel> Vignette(source, GraphicsOptions.Default);
=> Vignette(source, GraphicsOptions.Default);
/// <summary> /// <summary>
/// Applies a radial vignette effect to an image. /// Applies a radial vignette effect to an image.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="source">The image this method extends.</param> /// <param name="source">The image this method extends.</param>
/// <param name="color">The color to set as the vignette.</param> /// <param name="color">The color to set as the vignette.</param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns> /// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
public static IImageProcessingContext<TPixel> Vignette<TPixel>(this IImageProcessingContext<TPixel> source, TPixel color) public static IImageProcessingContext Vignette(this IImageProcessingContext source, Color color) =>
where TPixel : struct, IPixel<TPixel> Vignette(source, GraphicsOptions.Default, color);
=> Vignette(source, GraphicsOptions.Default, color);
/// <summary> /// <summary>
/// Applies a radial vignette effect to an image. /// Applies a radial vignette effect to an image.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="source">The image this method extends.</param> /// <param name="source">The image this method extends.</param>
/// <param name="radiusX">The the x-radius.</param> /// <param name="radiusX">The the x-radius.</param>
/// <param name="radiusY">The the y-radius.</param> /// <param name="radiusY">The the y-radius.</param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns> /// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
public static IImageProcessingContext<TPixel> Vignette<TPixel>(this IImageProcessingContext<TPixel> source, float radiusX, float radiusY) public static IImageProcessingContext Vignette(
where TPixel : struct, IPixel<TPixel> this IImageProcessingContext source,
=> Vignette(source, GraphicsOptions.Default, radiusX, radiusY); float radiusX,
float radiusY) =>
Vignette(source, GraphicsOptions.Default, radiusX, radiusY);
/// <summary> /// <summary>
/// Applies a radial vignette effect to an image. /// Applies a radial vignette effect to an image.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="source">The image this method extends.</param> /// <param name="source">The image this method extends.</param>
/// <param name="rectangle"> /// <param name="rectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter. /// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
/// </param> /// </param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns> /// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
public static IImageProcessingContext<TPixel> Vignette<TPixel>(this IImageProcessingContext<TPixel> source, Rectangle rectangle) public static IImageProcessingContext Vignette(this IImageProcessingContext source, Rectangle rectangle) =>
where TPixel : struct, IPixel<TPixel> Vignette(source, GraphicsOptions.Default, rectangle);
=> Vignette(source, GraphicsOptions.Default, rectangle);
/// <summary> /// <summary>
/// Applies a radial vignette effect to an image. /// Applies a radial vignette effect to an image.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="source">The image this method extends.</param> /// <param name="source">The image this method extends.</param>
/// <param name="color">The color to set as the vignette.</param> /// <param name="color">The color to set as the vignette.</param>
/// <param name="radiusX">The the x-radius.</param> /// <param name="radiusX">The the x-radius.</param>
@ -72,64 +65,82 @@ namespace SixLabors.ImageSharp.Processing
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter. /// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
/// </param> /// </param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns> /// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
public static IImageProcessingContext<TPixel> Vignette<TPixel>(this IImageProcessingContext<TPixel> source, TPixel color, float radiusX, float radiusY, Rectangle rectangle) public static IImageProcessingContext Vignette(
where TPixel : struct, IPixel<TPixel> this IImageProcessingContext source,
=> source.Vignette(GraphicsOptions.Default, color, radiusX, radiusY, rectangle); Color color,
float radiusX,
float radiusY,
Rectangle rectangle) =>
source.Vignette(GraphicsOptions.Default, color, radiusX, radiusY, rectangle);
/// <summary> /// <summary>
/// Applies a radial vignette effect to an image. /// Applies a radial vignette effect to an image.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="source">The image this method extends.</param> /// <param name="source">The image this method extends.</param>
/// <param name="options">The options effecting pixel blending.</param> /// <param name="options">The options effecting pixel blending.</param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns> /// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
public static IImageProcessingContext<TPixel> Vignette<TPixel>(this IImageProcessingContext<TPixel> source, GraphicsOptions options) public static IImageProcessingContext Vignette(this IImageProcessingContext source, GraphicsOptions options) =>
where TPixel : struct, IPixel<TPixel> source.VignetteInternal(
=> source.VignetteInternal(options, NamedColors<TPixel>.Black, ValueSize.PercentageOfWidth(.5f), ValueSize.PercentageOfHeight(.5f)); options,
Color.Black,
ValueSize.PercentageOfWidth(.5f),
ValueSize.PercentageOfHeight(.5f));
/// <summary> /// <summary>
/// Applies a radial vignette effect to an image. /// Applies a radial vignette effect to an image.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="source">The image this method extends.</param> /// <param name="source">The image this method extends.</param>
/// <param name="options">The options effecting pixel blending.</param> /// <param name="options">The options effecting pixel blending.</param>
/// <param name="color">The color to set as the vignette.</param> /// <param name="color">The color to set as the vignette.</param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns> /// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
public static IImageProcessingContext<TPixel> Vignette<TPixel>(this IImageProcessingContext<TPixel> source, GraphicsOptions options, TPixel color) public static IImageProcessingContext Vignette(
where TPixel : struct, IPixel<TPixel> this IImageProcessingContext source,
=> source.VignetteInternal(options, color, ValueSize.PercentageOfWidth(.5f), ValueSize.PercentageOfHeight(.5f)); GraphicsOptions options,
Color color) =>
source.VignetteInternal(
options,
color,
ValueSize.PercentageOfWidth(.5f),
ValueSize.PercentageOfHeight(.5f));
/// <summary> /// <summary>
/// Applies a radial vignette effect to an image. /// Applies a radial vignette effect to an image.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="source">The image this method extends.</param> /// <param name="source">The image this method extends.</param>
/// <param name="options">The options effecting pixel blending.</param> /// <param name="options">The options effecting pixel blending.</param>
/// <param name="radiusX">The the x-radius.</param> /// <param name="radiusX">The the x-radius.</param>
/// <param name="radiusY">The the y-radius.</param> /// <param name="radiusY">The the y-radius.</param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns> /// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
public static IImageProcessingContext<TPixel> Vignette<TPixel>(this IImageProcessingContext<TPixel> source, GraphicsOptions options, float radiusX, float radiusY) public static IImageProcessingContext Vignette(
where TPixel : struct, IPixel<TPixel> this IImageProcessingContext source,
=> source.VignetteInternal(options, NamedColors<TPixel>.Black, radiusX, radiusY); GraphicsOptions options,
float radiusX,
float radiusY) =>
source.VignetteInternal(options, Color.Black, radiusX, radiusY);
/// <summary> /// <summary>
/// Applies a radial vignette effect to an image. /// Applies a radial vignette effect to an image.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="source">The image this method extends.</param> /// <param name="source">The image this method extends.</param>
/// <param name="options">The options effecting pixel blending.</param> /// <param name="options">The options effecting pixel blending.</param>
/// <param name="rectangle"> /// <param name="rectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter. /// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
/// </param> /// </param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns> /// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
public static IImageProcessingContext<TPixel> Vignette<TPixel>(this IImageProcessingContext<TPixel> source, GraphicsOptions options, Rectangle rectangle) public static IImageProcessingContext Vignette(
where TPixel : struct, IPixel<TPixel> this IImageProcessingContext source,
=> source.VignetteInternal(options, NamedColors<TPixel>.Black, ValueSize.PercentageOfWidth(.5f), ValueSize.PercentageOfHeight(.5f), rectangle); GraphicsOptions options,
Rectangle rectangle) =>
source.VignetteInternal(
options,
Color.Black,
ValueSize.PercentageOfWidth(.5f),
ValueSize.PercentageOfHeight(.5f),
rectangle);
/// <summary> /// <summary>
/// Applies a radial vignette effect to an image. /// Applies a radial vignette effect to an image.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="source">The image this method extends.</param> /// <param name="source">The image this method extends.</param>
/// <param name="options">The options effecting pixel blending.</param> /// <param name="options">The options effecting pixel blending.</param>
/// <param name="color">The color to set as the vignette.</param> /// <param name="color">The color to set as the vignette.</param>
@ -139,16 +150,30 @@ namespace SixLabors.ImageSharp.Processing
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter. /// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
/// </param> /// </param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns> /// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
public static IImageProcessingContext<TPixel> Vignette<TPixel>(this IImageProcessingContext<TPixel> source, GraphicsOptions options, TPixel color, float radiusX, float radiusY, Rectangle rectangle) public static IImageProcessingContext Vignette(
where TPixel : struct, IPixel<TPixel> this IImageProcessingContext source,
=> source.VignetteInternal(options, color, radiusX, radiusY, rectangle); GraphicsOptions options,
Color color,
float radiusX,
float radiusY,
Rectangle rectangle) =>
source.VignetteInternal(options, color, radiusX, radiusY, rectangle);
private static IImageProcessingContext<TPixel> VignetteInternal<TPixel>(this IImageProcessingContext<TPixel> source, GraphicsOptions options, TPixel color, ValueSize radiusX, ValueSize radiusY, Rectangle rectangle) private static IImageProcessingContext VignetteInternal(
where TPixel : struct, IPixel<TPixel> this IImageProcessingContext source,
=> source.ApplyProcessor(new VignetteProcessor<TPixel>(color, radiusX, radiusY, options), rectangle); GraphicsOptions options,
Color color,
ValueSize radiusX,
ValueSize radiusY,
Rectangle rectangle) =>
source.ApplyProcessor(new VignetteProcessor(color, radiusX, radiusY, options), rectangle);
private static IImageProcessingContext<TPixel> VignetteInternal<TPixel>(this IImageProcessingContext<TPixel> source, GraphicsOptions options, TPixel color, ValueSize radiusX, ValueSize radiusY) private static IImageProcessingContext VignetteInternal(
where TPixel : struct, IPixel<TPixel> this IImageProcessingContext source,
=> source.ApplyProcessor(new VignetteProcessor<TPixel>(color, radiusX, radiusY, options)); GraphicsOptions options,
Color color,
ValueSize radiusX,
ValueSize radiusY) =>
source.ApplyProcessor(new VignetteProcessor(color, radiusX, radiusY, options));
} }
} }

4
tests/ImageSharp.Benchmarks/Samplers/Glow.cs

@ -20,14 +20,14 @@ namespace SixLabors.ImageSharp.Benchmarks
public class Glow : BenchmarkBase public class Glow : BenchmarkBase
{ {
private GlowProcessor<Rgba32> bulk; private GlowProcessor bulk;
private GlowProcessorParallel<Rgba32> parallel; private GlowProcessorParallel<Rgba32> parallel;
[GlobalSetup] [GlobalSetup]
public void Setup() public void Setup()
{ {
this.bulk = new GlowProcessor<Rgba32>(NamedColors<Rgba32>.Beige, 800 * .5f, GraphicsOptions.Default); this.bulk = new GlowProcessor(Color.Beige, 800 * .5f, GraphicsOptions.Default);
this.parallel = new GlowProcessorParallel<Rgba32>(NamedColors<Rgba32>.Beige) { Radius = 800 * .5f, }; this.parallel = new GlowProcessorParallel<Rgba32>(NamedColors<Rgba32>.Beige) { Radius = 800 * .5f, };
} }

6
tests/ImageSharp.Tests/Drawing/BeziersTests.cs

@ -19,8 +19,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing
string path = TestEnvironment.CreateOutputDirectory("Drawing", "BezierLine"); string path = TestEnvironment.CreateOutputDirectory("Drawing", "BezierLine");
using (var image = new Image<Rgba32>(500, 500)) using (var image = new Image<Rgba32>(500, 500))
{ {
image.Mutate(x => x.BackgroundColor(Color.Blue));
image.Mutate( image.Mutate(
x => x.BackgroundColor(Rgba32.Blue).DrawBeziers( x => x.DrawBeziers(
Rgba32.HotPink, Rgba32.HotPink,
5, 5,
new SixLabors.Primitives.PointF[] new SixLabors.Primitives.PointF[]
@ -56,8 +57,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing
using (var image = new Image<Rgba32>(500, 500)) using (var image = new Image<Rgba32>(500, 500))
{ {
image.Mutate(x => x.BackgroundColor(Color.Blue));
image.Mutate( image.Mutate(
x => x.BackgroundColor(Rgba32.Blue).DrawBeziers( x => x.DrawBeziers(
color, color,
10, 10,
new SixLabors.Primitives.PointF[] new SixLabors.Primitives.PointF[]

2
tests/ImageSharp.Tests/Drawing/DrawImageTest.cs

@ -80,7 +80,7 @@ namespace SixLabors.ImageSharp.Tests
// Apply a background color so we can see the translation. // Apply a background color so we can see the translation.
blend.Mutate(x => x.Transform(builder)); blend.Mutate(x => x.Transform(builder));
blend.Mutate(x => x.BackgroundColor(NamedColors<TPixel>.HotPink)); blend.Mutate(x => x.BackgroundColor(Color.HotPink));
// Lets center the matrix so we can tell whether any cut-off issues we may have belong to the drawing processor // Lets center the matrix so we can tell whether any cut-off issues we may have belong to the drawing processor
var position = new Point((image.Width - blend.Width) / 2, (image.Height - blend.Height) / 2); var position = new Point((image.Width - blend.Width) / 2, (image.Height - blend.Height) / 2);

8
tests/ImageSharp.Tests/Drawing/DrawPathTests.cs

@ -30,8 +30,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing
new Vector2(10, 400)); new Vector2(10, 400));
var p = new Path(linerSegemnt, bazierSegment); var p = new Path(linerSegemnt, bazierSegment);
image.Mutate(x => x.BackgroundColor(Rgba32.Blue).Draw(Rgba32.HotPink, 5, p)); image.Mutate(x => x.BackgroundColor(Rgba32.Blue));
image.Mutate(x => x.Draw(Rgba32.HotPink, 5, p));
image.Save($"{path}/Simple.png"); image.Save($"{path}/Simple.png");
Buffer2D<Rgba32> sourcePixels = image.GetRootFramePixelBuffer(); Buffer2D<Rgba32> sourcePixels = image.GetRootFramePixelBuffer();
@ -67,7 +68,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing
using (var image = new Image<Rgba32>(500, 500)) using (var image = new Image<Rgba32>(500, 500))
{ {
image.Mutate(x => x.BackgroundColor(Rgba32.Blue).Draw(color, 10, p)); image.Mutate(x => x.BackgroundColor(Rgba32.Blue));
image.Mutate(x => x.Draw(color, 10, p));
image.Save($"{path}/Opacity.png"); image.Save($"{path}/Opacity.png");
//shift background color towards forground color by the opacity amount //shift background color towards forground color by the opacity amount

17
tests/ImageSharp.Tests/Drawing/LineComplexPolygonTests.cs

@ -31,7 +31,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing
using (var image = new Image<Rgba32>(500, 500)) using (var image = new Image<Rgba32>(500, 500))
{ {
image.Mutate(x => x.BackgroundColor(Rgba32.Blue).Draw(Rgba32.HotPink, 5, simplePath.Clip(hole1))); image.Mutate(x => x.BackgroundColor(Rgba32.Blue));
image.Mutate(x => x.Draw(Rgba32.HotPink, 5, simplePath.Clip(hole1)));
image.Save($"{path}/Simple.png"); image.Save($"{path}/Simple.png");
Buffer2D<Rgba32> sourcePixels = image.GetRootFramePixelBuffer(); Buffer2D<Rgba32> sourcePixels = image.GetRootFramePixelBuffer();
@ -73,7 +74,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing
using (var image = new Image<Rgba32>(500, 500)) using (var image = new Image<Rgba32>(500, 500))
{ {
image.Mutate(x => x.BackgroundColor(Rgba32.Blue).Draw(Rgba32.HotPink, 5, simplePath.Clip(hole1))); image.Mutate(x => x.BackgroundColor(Rgba32.Blue));
image.Mutate(x => x.Draw(Rgba32.HotPink, 5, simplePath.Clip(hole1)));
image.Save($"{path}/SimpleVanishHole.png"); image.Save($"{path}/SimpleVanishHole.png");
Buffer2D<Rgba32> sourcePixels = image.GetRootFramePixelBuffer(); Buffer2D<Rgba32> sourcePixels = image.GetRootFramePixelBuffer();
@ -113,7 +115,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing
using (var image = new Image<Rgba32>(500, 500)) using (var image = new Image<Rgba32>(500, 500))
{ {
image.Mutate(x => x.BackgroundColor(Rgba32.Blue).Draw(Rgba32.HotPink, 5, simplePath.Clip(hole1))); image.Mutate(x => x.BackgroundColor(Rgba32.Blue));
image.Mutate(x => x.Draw(Rgba32.HotPink, 5, simplePath.Clip(hole1)));
image.Save($"{path}/SimpleOverlapping.png"); image.Save($"{path}/SimpleOverlapping.png");
Buffer2D<Rgba32> sourcePixels = image.GetRootFramePixelBuffer(); Buffer2D<Rgba32> sourcePixels = image.GetRootFramePixelBuffer();
@ -147,9 +150,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing
using (var image = new Image<Rgba32>(500, 500)) using (var image = new Image<Rgba32>(500, 500))
{ {
image.Mutate(x => x image.Mutate(x => x.BackgroundColor(Rgba32.Blue));
.BackgroundColor(Rgba32.Blue) image.Mutate(x => x.Draw(Pens.Dash(Rgba32.HotPink, 5), simplePath.Clip(hole1)));
.Draw(Pens.Dash(Rgba32.HotPink, 5), simplePath.Clip(hole1)));
image.Save($"{path}/Dashed.png"); image.Save($"{path}/Dashed.png");
} }
} }
@ -171,7 +173,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing
using (var image = new Image<Rgba32>(500, 500)) using (var image = new Image<Rgba32>(500, 500))
{ {
image.Mutate(x => x.BackgroundColor(Rgba32.Blue).Draw(color, 5, simplePath.Clip(hole1))); image.Mutate(x => x.BackgroundColor(Rgba32.Blue));
image.Mutate(x => x.Draw(color, 5, simplePath.Clip(hole1)));
image.Save($"{path}/Opacity.png"); image.Save($"{path}/Opacity.png");
//shift background color towards forground color by the opacity amount //shift background color towards forground color by the opacity amount

33
tests/ImageSharp.Tests/Drawing/LineTests.cs

@ -19,8 +19,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing
string path = TestEnvironment.CreateOutputDirectory("Drawing", "Lines"); string path = TestEnvironment.CreateOutputDirectory("Drawing", "Lines");
using (var image = new Image<Rgba32>(500, 500)) using (var image = new Image<Rgba32>(500, 500))
{ {
image.Mutate(x => x.BackgroundColor(Rgba32.Blue));
image.Mutate( image.Mutate(
x => x.BackgroundColor(Rgba32.Blue).DrawLines( x => x.DrawLines(
Rgba32.HotPink, Rgba32.HotPink,
5, 5,
new Vector2(10, 10), new Vector2(10, 10),
@ -43,8 +44,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing
string path = TestEnvironment.CreateOutputDirectory("Drawing", "Lines"); string path = TestEnvironment.CreateOutputDirectory("Drawing", "Lines");
using (var image = new Image<Rgba32>(500, 500)) using (var image = new Image<Rgba32>(500, 500))
{ {
image.Mutate(x => x.BackgroundColor(Rgba32.Blue));
image.Mutate( image.Mutate(
x => x.BackgroundColor(Rgba32.Blue).DrawLines( x => x.DrawLines(
new GraphicsOptions(false), new GraphicsOptions(false),
Rgba32.HotPink, Rgba32.HotPink,
5, 5,
@ -68,9 +70,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing
string path = TestEnvironment.CreateOutputDirectory("Drawing", "Lines"); string path = TestEnvironment.CreateOutputDirectory("Drawing", "Lines");
using (var image = new Image<Rgba32>(500, 500)) using (var image = new Image<Rgba32>(500, 500))
{ {
image.Mutate(x => x image.Mutate(x => x.BackgroundColor(Rgba32.Blue));
.BackgroundColor(Rgba32.Blue) image.Mutate(x => x.DrawLines(Pens.Dash(Rgba32.HotPink, 5),
.DrawLines(Pens.Dash(Rgba32.HotPink, 5),
new SixLabors.Primitives.PointF[] { new SixLabors.Primitives.PointF[] {
new Vector2(10, 10), new Vector2(10, 10),
new Vector2(200, 150), new Vector2(200, 150),
@ -86,9 +87,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing
string path = TestEnvironment.CreateOutputDirectory("Drawing", "Lines"); string path = TestEnvironment.CreateOutputDirectory("Drawing", "Lines");
using (var image = new Image<Rgba32>(500, 500)) using (var image = new Image<Rgba32>(500, 500))
{ {
image.Mutate(x => x image.Mutate(x => x.BackgroundColor(Rgba32.Blue));
.BackgroundColor(Rgba32.Blue) image.Mutate(x => x.DrawLines(Pens.Dot(Rgba32.HotPink, 5),
.DrawLines(Pens.Dot(Rgba32.HotPink, 5),
new SixLabors.Primitives.PointF[] { new SixLabors.Primitives.PointF[] {
new Vector2(10, 10), new Vector2(10, 10),
new Vector2(200, 150), new Vector2(200, 150),
@ -104,9 +104,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing
string path = TestEnvironment.CreateOutputDirectory("Drawing", "Lines"); string path = TestEnvironment.CreateOutputDirectory("Drawing", "Lines");
using (var image = new Image<Rgba32>(500, 500)) using (var image = new Image<Rgba32>(500, 500))
{ {
image.Mutate(x => x image.Mutate(x => x.BackgroundColor(Rgba32.Blue));
.BackgroundColor(Rgba32.Blue) image.Mutate(x => x.DrawLines(Pens.DashDot(Rgba32.HotPink, 5),
.DrawLines(Pens.DashDot(Rgba32.HotPink, 5),
new SixLabors.Primitives.PointF[] { new SixLabors.Primitives.PointF[] {
new Vector2(10, 10), new Vector2(10, 10),
new Vector2(200, 150), new Vector2(200, 150),
@ -122,9 +121,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing
string path = TestEnvironment.CreateOutputDirectory("Drawing", "Lines"); string path = TestEnvironment.CreateOutputDirectory("Drawing", "Lines");
var image = new Image<Rgba32>(500, 500); var image = new Image<Rgba32>(500, 500);
image.Mutate(x => x image.Mutate(x => x.BackgroundColor(Rgba32.Blue));
.BackgroundColor(Rgba32.Blue) image.Mutate(x => x.DrawLines(Pens.DashDotDot(Rgba32.HotPink, 5),
.DrawLines(Pens.DashDotDot(Rgba32.HotPink, 5), new SixLabors.Primitives.PointF[] { new SixLabors.Primitives.PointF[] {
new Vector2(10, 10), new Vector2(10, 10),
new Vector2(200, 150), new Vector2(200, 150),
new Vector2(50, 300) new Vector2(50, 300)
@ -141,8 +140,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing
var image = new Image<Rgba32>(500, 500); var image = new Image<Rgba32>(500, 500);
image.Mutate(x => x.BackgroundColor(Rgba32.Blue));
image.Mutate( image.Mutate(
x => x.BackgroundColor(Rgba32.Blue).DrawLines( x => x.DrawLines(
color, color,
10, 10,
new Vector2(10, 10), new Vector2(10, 10),
@ -169,8 +169,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing
var image = new Image<Rgba32>(500, 500); var image = new Image<Rgba32>(500, 500);
image.Mutate(x => x.BackgroundColor(Rgba32.Blue));
image.Mutate( image.Mutate(
x => x.BackgroundColor(Rgba32.Blue).DrawLines( x => x.DrawLines(
Rgba32.HotPink, Rgba32.HotPink,
10, 10,
new Vector2(10, 10), new Vector2(10, 10),

9
tests/ImageSharp.Tests/Drawing/PolygonTests.cs

@ -20,8 +20,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing
using (Image<Rgba32> image = new Image<Rgba32>(500, 500)) using (Image<Rgba32> image = new Image<Rgba32>(500, 500))
{ {
image.Mutate(x => x.BackgroundColor(Rgba32.Blue));
image.Mutate( image.Mutate(
x => x.BackgroundColor(Rgba32.Blue).DrawPolygon( x => x.DrawPolygon(
Rgba32.HotPink, Rgba32.HotPink,
5, 5,
new Vector2(10, 10), new Vector2(10, 10),
@ -54,7 +55,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing
using (Image<Rgba32> image = new Image<Rgba32>(500, 500)) using (Image<Rgba32> image = new Image<Rgba32>(500, 500))
{ {
image.Mutate(x => x.BackgroundColor(Rgba32.Blue).DrawPolygon(color, 10, simplePath)); image.Mutate(x => x.BackgroundColor(Rgba32.Blue));
image.Mutate(x => x.DrawPolygon(color, 10, simplePath));
image.Save($"{path}/Opacity.png"); image.Save($"{path}/Opacity.png");
//shift background color towards forground color by the opacity amount //shift background color towards forground color by the opacity amount
@ -79,8 +81,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing
using (Image<Rgba32> image = new Image<Rgba32>(500, 500)) using (Image<Rgba32> image = new Image<Rgba32>(500, 500))
{ {
image.Mutate(x => x.BackgroundColor(Rgba32.Blue));
image.Mutate( image.Mutate(
x => x.BackgroundColor(Rgba32.Blue).Draw(Rgba32.HotPink, 10, new Rectangle(10, 10, 190, 140))); x => x.Draw(Rgba32.HotPink, 10, new Rectangle(10, 10, 190, 140)));
image.Save($"{path}/Rectangle.png"); image.Save($"{path}/Rectangle.png");
Buffer2D<Rgba32> sourcePixels = image.GetRootFramePixelBuffer(); Buffer2D<Rgba32> sourcePixels = image.GetRootFramePixelBuffer();

16
tests/ImageSharp.Tests/Drawing/SolidBezierTests.cs

@ -24,15 +24,13 @@ namespace SixLabors.ImageSharp.Tests.Drawing
new Vector2(300, 400) new Vector2(300, 400)
}; };
TPixel blue = NamedColors<TPixel>.Blue; Color blue = Color.Blue;
TPixel hotPink = NamedColors<TPixel>.HotPink; Color hotPink = Color.HotPink;
using (Image<TPixel> image = provider.GetImage()) using (Image<TPixel> image = provider.GetImage())
{ {
image.Mutate(x => x.BackgroundColor(blue));
image.Mutate(x => x image.Mutate(x => x.Fill(hotPink.ToPixel<TPixel>(), new Polygon(new CubicBezierLineSegment(simplePath))));
.BackgroundColor(blue)
.Fill(hotPink, new Polygon(new CubicBezierLineSegment(simplePath))));
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToReferenceOutput(provider); image.CompareToReferenceOutput(provider);
} }
@ -55,9 +53,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing
using (var image = provider.GetImage() as Image<Rgba32>) using (var image = provider.GetImage() as Image<Rgba32>)
{ {
image.Mutate(x => x image.Mutate(x => x.BackgroundColor(Rgba32.Blue));
.BackgroundColor(Rgba32.Blue)
.Fill(color, new Polygon(new CubicBezierLineSegment(simplePath)))); image.Mutate(x => x.Fill(color, new Polygon(new CubicBezierLineSegment(simplePath))));
image.DebugSave(provider); image.DebugSave(provider);
image.CompareToReferenceOutput(provider); image.CompareToReferenceOutput(provider);
} }

9
tests/ImageSharp.Tests/Drawing/SolidComplexPolygonTests.cs

@ -31,7 +31,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing
// var clipped = new Rectangle(10, 10, 100, 100).Clip(new Rectangle(20, 0, 20, 20)); // var clipped = new Rectangle(10, 10, 100, 100).Clip(new Rectangle(20, 0, 20, 20));
using (var image = new Image<Rgba32>(500, 500)) using (var image = new Image<Rgba32>(500, 500))
{ {
image.Mutate(x => x.BackgroundColor(Rgba32.Blue).Fill(Rgba32.HotPink, clipped)); image.Mutate(x => x.BackgroundColor(Rgba32.Blue));
image.Mutate(x => x.Fill(Rgba32.HotPink, clipped));
image.Save($"{path}/Simple.png"); image.Save($"{path}/Simple.png");
Buffer2D<Rgba32> sourcePixels = image.GetRootFramePixelBuffer(); Buffer2D<Rgba32> sourcePixels = image.GetRootFramePixelBuffer();
@ -59,7 +60,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing
using (var image = new Image<Rgba32>(500, 500)) using (var image = new Image<Rgba32>(500, 500))
{ {
image.Mutate(x => x.BackgroundColor(Rgba32.Blue).Fill(Rgba32.HotPink, simplePath.Clip(hole1))); image.Mutate(x => x.BackgroundColor(Rgba32.Blue));
image.Mutate(x => x.Fill(Rgba32.HotPink, simplePath.Clip(hole1)));
image.Save($"{path}/SimpleOverlapping.png"); image.Save($"{path}/SimpleOverlapping.png");
Buffer2D<Rgba32> sourcePixels = image.GetRootFramePixelBuffer(); Buffer2D<Rgba32> sourcePixels = image.GetRootFramePixelBuffer();
@ -88,7 +90,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing
using (var image = new Image<Rgba32>(500, 500)) using (var image = new Image<Rgba32>(500, 500))
{ {
image.Mutate(x => x.BackgroundColor(Rgba32.Blue).Fill(color, simplePath.Clip(hole1))); image.Mutate(x => x.BackgroundColor(Rgba32.Blue));
image.Mutate(x => x.Fill(color, simplePath.Clip(hole1)));
image.Save($"{path}/Opacity.png"); image.Save($"{path}/Opacity.png");
//shift background color towards forground color by the opacity amount //shift background color towards forground color by the opacity amount

25
tests/ImageSharp.Tests/Drawing/SolidPolygonTests.cs

@ -68,8 +68,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing
using (var image = new Image<Rgba32>(500, 500)) using (var image = new Image<Rgba32>(500, 500))
{ {
image.Mutate(x => x.BackgroundColor(Rgba32.Blue));
image.Mutate( image.Mutate(
x => x.BackgroundColor(Rgba32.Blue).FillPolygon( x => x.FillPolygon(
new GraphicsOptions(false), new GraphicsOptions(false),
Rgba32.HotPink, Rgba32.HotPink,
simplePath)); simplePath));
@ -101,9 +102,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing
{ {
var brush = new ImageBrush<Rgba32>(brushImage); var brush = new ImageBrush<Rgba32>(brushImage);
image.Mutate(x => x image.Mutate(x => x.BackgroundColor(Rgba32.Blue));
.BackgroundColor(Rgba32.Blue) image.Mutate(x => x.FillPolygon(brush, simplePath));
.FillPolygon(brush, simplePath));
image.Save($"{path}/Image.png"); image.Save($"{path}/Image.png");
} }
} }
@ -121,7 +121,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing
using (var image = new Image<Rgba32>(500, 500)) using (var image = new Image<Rgba32>(500, 500))
{ {
image.Mutate(x => x.BackgroundColor(Rgba32.Blue).FillPolygon(color, simplePath)); image.Mutate(x => x.BackgroundColor(Rgba32.Blue));
image.Mutate(x => x.FillPolygon(color, simplePath));
image.Save($"{path}/Opacity.png"); image.Save($"{path}/Opacity.png");
//shift background color towards forground color by the opacity amount //shift background color towards forground color by the opacity amount
@ -140,8 +141,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing
using (var image = new Image<Rgba32>(500, 500)) using (var image = new Image<Rgba32>(500, 500))
{ {
image.Mutate(x => x.BackgroundColor(Rgba32.Blue));
image.Mutate( image.Mutate(
x => x.BackgroundColor(Rgba32.Blue).Fill( x => x.Fill(
Rgba32.HotPink, Rgba32.HotPink,
new SixLabors.Shapes.RectangularPolygon(10, 10, 190, 140))); new SixLabors.Shapes.RectangularPolygon(10, 10, 190, 140)));
image.Save($"{path}/Rectangle.png"); image.Save($"{path}/Rectangle.png");
@ -166,8 +168,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing
using (var image = new Image<Rgba32>(100, 100)) using (var image = new Image<Rgba32>(100, 100))
{ {
image.Mutate(x => x.BackgroundColor(Rgba32.Blue));
image.Mutate( image.Mutate(
x => x.BackgroundColor(Rgba32.Blue).Fill(Rgba32.HotPink, new RegularPolygon(50, 50, 3, 30))); x => x.Fill(Rgba32.HotPink, new RegularPolygon(50, 50, 3, 30)));
image.Save($"{path}/Triangle.png"); image.Save($"{path}/Triangle.png");
Buffer2D<Rgba32> sourcePixels = image.GetRootFramePixelBuffer(); Buffer2D<Rgba32> sourcePixels = image.GetRootFramePixelBuffer();
@ -186,9 +189,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing
config.MaxDegreeOfParallelism = 1; config.MaxDegreeOfParallelism = 1;
using (var image = new Image<Rgba32>(config, 100, 100)) using (var image = new Image<Rgba32>(config, 100, 100))
{ {
image.Mutate(x => x image.Mutate(x => x.BackgroundColor(Rgba32.Blue));
.BackgroundColor(Rgba32.Blue) image.Mutate(x => x.Fill(Rgba32.HotPink,
.Fill(Rgba32.HotPink, new RegularPolygon(50, 50, 7, 30, -(float)Math.PI))); new RegularPolygon(50, 50, 7, 30, -(float)Math.PI)));
image.Save($"{path}/Septagon.png"); image.Save($"{path}/Septagon.png");
} }
} }
@ -202,8 +205,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing
config.MaxDegreeOfParallelism = 1; config.MaxDegreeOfParallelism = 1;
using (var image = new Image<Rgba32>(config, 100, 100)) using (var image = new Image<Rgba32>(config, 100, 100))
{ {
image.Mutate(x => x.BackgroundColor(Rgba32.Blue));
image.Mutate(x => x image.Mutate(x => x
.BackgroundColor(Rgba32.Blue)
.Fill(Rgba32.HotPink, new EllipsePolygon(50, 50, 30, 50) .Fill(Rgba32.HotPink, new EllipsePolygon(50, 50, 30, 50)
.Rotate((float)(Math.PI / 3)))); .Rotate((float)(Math.PI / 3))));
image.Save($"{path}/ellipse.png"); image.Save($"{path}/ellipse.png");

24
tests/ImageSharp.Tests/Processing/Effects/BackgroundColorTest.cs

@ -14,41 +14,41 @@ namespace SixLabors.ImageSharp.Tests.Processing.Effects
[Fact] [Fact]
public void BackgroundColor_amount_BackgroundColorProcessorDefaultsSet() public void BackgroundColor_amount_BackgroundColorProcessorDefaultsSet()
{ {
this.operations.BackgroundColor(Rgba32.BlanchedAlmond); this.operations.BackgroundColor(Color.BlanchedAlmond);
var processor = this.Verify<BackgroundColorProcessor<Rgba32>>(); var processor = this.Verify<BackgroundColorProcessor>();
Assert.Equal(GraphicsOptions.Default, processor.GraphicsOptions); Assert.Equal(GraphicsOptions.Default, processor.GraphicsOptions);
Assert.Equal(Rgba32.BlanchedAlmond, processor.Color); Assert.Equal(Color.BlanchedAlmond, processor.Color);
} }
[Fact] [Fact]
public void BackgroundColor_amount_rect_BackgroundColorProcessorDefaultsSet() public void BackgroundColor_amount_rect_BackgroundColorProcessorDefaultsSet()
{ {
this.operations.BackgroundColor(Rgba32.BlanchedAlmond, this.rect); this.operations.BackgroundColor(Color.BlanchedAlmond, this.rect);
var processor = this.Verify<BackgroundColorProcessor<Rgba32>>(this.rect); var processor = this.Verify<BackgroundColorProcessor>(this.rect);
Assert.Equal(GraphicsOptions.Default, processor.GraphicsOptions); Assert.Equal(GraphicsOptions.Default, processor.GraphicsOptions);
Assert.Equal(Rgba32.BlanchedAlmond, processor.Color); Assert.Equal(Color.BlanchedAlmond, processor.Color);
} }
[Fact] [Fact]
public void BackgroundColor_amount_options_BackgroundColorProcessorDefaultsSet() public void BackgroundColor_amount_options_BackgroundColorProcessorDefaultsSet()
{ {
this.operations.BackgroundColor(this.options, Rgba32.BlanchedAlmond); this.operations.BackgroundColor(this.options, Color.BlanchedAlmond);
var processor = this.Verify<BackgroundColorProcessor<Rgba32>>(); var processor = this.Verify<BackgroundColorProcessor>();
Assert.Equal(this.options, processor.GraphicsOptions); Assert.Equal(this.options, processor.GraphicsOptions);
Assert.Equal(Rgba32.BlanchedAlmond, processor.Color); Assert.Equal(Color.BlanchedAlmond, processor.Color);
} }
[Fact] [Fact]
public void BackgroundColor_amount_rect_options_BackgroundColorProcessorDefaultsSet() public void BackgroundColor_amount_rect_options_BackgroundColorProcessorDefaultsSet()
{ {
this.operations.BackgroundColor(this.options, Rgba32.BlanchedAlmond, this.rect); this.operations.BackgroundColor(this.options, Color.BlanchedAlmond, this.rect);
var processor = this.Verify<BackgroundColorProcessor<Rgba32>>(this.rect); var processor = this.Verify<BackgroundColorProcessor>(this.rect);
Assert.Equal(this.options, processor.GraphicsOptions); Assert.Equal(this.options, processor.GraphicsOptions);
Assert.Equal(Rgba32.BlanchedAlmond, processor.Color); Assert.Equal(Color.BlanchedAlmond, processor.Color);
} }
} }
} }

16
tests/ImageSharp.Tests/Processing/Overlays/GlowTest.cs

@ -18,10 +18,10 @@ namespace SixLabors.ImageSharp.Tests.Processing.Overlays
public void Glow_GlowProcessorWithDefaultValues() public void Glow_GlowProcessorWithDefaultValues()
{ {
this.operations.Glow(); this.operations.Glow();
var p = this.Verify<GlowProcessor<Rgba32>>(); var p = this.Verify<GlowProcessor>();
Assert.Equal(GraphicsOptions.Default, p.GraphicsOptions); Assert.Equal(GraphicsOptions.Default, p.GraphicsOptions);
Assert.Equal(Rgba32.Black, p.GlowColor); Assert.Equal(Color.Black, p.GlowColor);
Assert.Equal(ValueSize.PercentageOfWidth(.5f), p.Radius); Assert.Equal(ValueSize.PercentageOfWidth(.5f), p.Radius);
} }
@ -29,10 +29,10 @@ namespace SixLabors.ImageSharp.Tests.Processing.Overlays
public void Glow_Color_GlowProcessorWithDefaultValues() public void Glow_Color_GlowProcessorWithDefaultValues()
{ {
this.operations.Glow(Rgba32.Aquamarine); this.operations.Glow(Rgba32.Aquamarine);
var p = this.Verify<GlowProcessor<Rgba32>>(); var p = this.Verify<GlowProcessor>();
Assert.Equal(GraphicsOptions.Default, p.GraphicsOptions); Assert.Equal(GraphicsOptions.Default, p.GraphicsOptions);
Assert.Equal(Rgba32.Aquamarine, p.GlowColor); Assert.Equal(Color.Aquamarine, p.GlowColor);
Assert.Equal(ValueSize.PercentageOfWidth(.5f), p.Radius); Assert.Equal(ValueSize.PercentageOfWidth(.5f), p.Radius);
} }
@ -40,10 +40,10 @@ namespace SixLabors.ImageSharp.Tests.Processing.Overlays
public void Glow_Radux_GlowProcessorWithDefaultValues() public void Glow_Radux_GlowProcessorWithDefaultValues()
{ {
this.operations.Glow(3.5f); this.operations.Glow(3.5f);
var p = this.Verify<GlowProcessor<Rgba32>>(); var p = this.Verify<GlowProcessor>();
Assert.Equal(GraphicsOptions.Default, p.GraphicsOptions); Assert.Equal(GraphicsOptions.Default, p.GraphicsOptions);
Assert.Equal(Rgba32.Black, p.GlowColor); Assert.Equal(Color.Black, p.GlowColor);
Assert.Equal(ValueSize.Absolute(3.5f), p.Radius); Assert.Equal(ValueSize.Absolute(3.5f), p.Radius);
} }
@ -52,10 +52,10 @@ namespace SixLabors.ImageSharp.Tests.Processing.Overlays
{ {
var rect = new Rectangle(12, 123, 43, 65); var rect = new Rectangle(12, 123, 43, 65);
this.operations.Glow(rect); this.operations.Glow(rect);
var p = this.Verify<GlowProcessor<Rgba32>>(rect); var p = this.Verify<GlowProcessor>(rect);
Assert.Equal(GraphicsOptions.Default, p.GraphicsOptions); Assert.Equal(GraphicsOptions.Default, p.GraphicsOptions);
Assert.Equal(Rgba32.Black, p.GlowColor); Assert.Equal(Color.Black, p.GlowColor);
Assert.Equal(ValueSize.PercentageOfWidth(.5f), p.Radius); Assert.Equal(ValueSize.PercentageOfWidth(.5f), p.Radius);
} }
} }

18
tests/ImageSharp.Tests/Processing/Overlays/VignetteTest.cs

@ -16,10 +16,10 @@ namespace SixLabors.ImageSharp.Tests.Processing.Overlays
public void Vignette_VignetteProcessorWithDefaultValues() public void Vignette_VignetteProcessorWithDefaultValues()
{ {
this.operations.Vignette(); this.operations.Vignette();
var p = this.Verify<VignetteProcessor<Rgba32>>(); var p = this.Verify<VignetteProcessor>();
Assert.Equal(GraphicsOptions.Default, p.GraphicsOptions); Assert.Equal(GraphicsOptions.Default, p.GraphicsOptions);
Assert.Equal(Rgba32.Black, p.VignetteColor); Assert.Equal(Color.Black, p.VignetteColor);
Assert.Equal(ValueSize.PercentageOfWidth(.5f), p.RadiusX); Assert.Equal(ValueSize.PercentageOfWidth(.5f), p.RadiusX);
Assert.Equal(ValueSize.PercentageOfHeight(.5f), p.RadiusY); Assert.Equal(ValueSize.PercentageOfHeight(.5f), p.RadiusY);
} }
@ -27,11 +27,11 @@ namespace SixLabors.ImageSharp.Tests.Processing.Overlays
[Fact] [Fact]
public void Vignette_Color_VignetteProcessorWithDefaultValues() public void Vignette_Color_VignetteProcessorWithDefaultValues()
{ {
this.operations.Vignette(Rgba32.Aquamarine); this.operations.Vignette(Color.Aquamarine);
var p = this.Verify<VignetteProcessor<Rgba32>>(); var p = this.Verify<VignetteProcessor>();
Assert.Equal(GraphicsOptions.Default, p.GraphicsOptions); Assert.Equal(GraphicsOptions.Default, p.GraphicsOptions);
Assert.Equal(Rgba32.Aquamarine, p.VignetteColor); Assert.Equal(Color.Aquamarine, p.VignetteColor);
Assert.Equal(ValueSize.PercentageOfWidth(.5f), p.RadiusX); Assert.Equal(ValueSize.PercentageOfWidth(.5f), p.RadiusX);
Assert.Equal(ValueSize.PercentageOfHeight(.5f), p.RadiusY); Assert.Equal(ValueSize.PercentageOfHeight(.5f), p.RadiusY);
} }
@ -40,10 +40,10 @@ namespace SixLabors.ImageSharp.Tests.Processing.Overlays
public void Vignette_Radux_VignetteProcessorWithDefaultValues() public void Vignette_Radux_VignetteProcessorWithDefaultValues()
{ {
this.operations.Vignette(3.5f, 12123f); this.operations.Vignette(3.5f, 12123f);
var p = this.Verify<VignetteProcessor<Rgba32>>(); var p = this.Verify<VignetteProcessor>();
Assert.Equal(GraphicsOptions.Default, p.GraphicsOptions); Assert.Equal(GraphicsOptions.Default, p.GraphicsOptions);
Assert.Equal(Rgba32.Black, p.VignetteColor); Assert.Equal(Color.Black, p.VignetteColor);
Assert.Equal(ValueSize.Absolute(3.5f), p.RadiusX); Assert.Equal(ValueSize.Absolute(3.5f), p.RadiusX);
Assert.Equal(ValueSize.Absolute(12123f), p.RadiusY); Assert.Equal(ValueSize.Absolute(12123f), p.RadiusY);
} }
@ -53,10 +53,10 @@ namespace SixLabors.ImageSharp.Tests.Processing.Overlays
{ {
var rect = new Rectangle(12, 123, 43, 65); var rect = new Rectangle(12, 123, 43, 65);
this.operations.Vignette(rect); this.operations.Vignette(rect);
var p = this.Verify<VignetteProcessor<Rgba32>>(rect); var p = this.Verify<VignetteProcessor>(rect);
Assert.Equal(GraphicsOptions.Default, p.GraphicsOptions); Assert.Equal(GraphicsOptions.Default, p.GraphicsOptions);
Assert.Equal(Rgba32.Black, p.VignetteColor); Assert.Equal(Color.Black, p.VignetteColor);
Assert.Equal(ValueSize.PercentageOfWidth(.5f), p.RadiusX); Assert.Equal(ValueSize.PercentageOfWidth(.5f), p.RadiusX);
Assert.Equal(ValueSize.PercentageOfHeight(.5f), p.RadiusY); Assert.Equal(ValueSize.PercentageOfHeight(.5f), p.RadiusY);
} }

4
tests/ImageSharp.Tests/Processing/Processors/Effects/BackgroundColorTest.cs

@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Effects
public void FullImage<TPixel>(TestImageProvider<TPixel> provider) public void FullImage<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
provider.RunValidatingProcessorTest(x => x.BackgroundColor(NamedColors<TPixel>.HotPink)); provider.RunValidatingProcessorTest(x => x.BackgroundColor(Color.HotPink));
} }
[Theory] [Theory]
@ -33,7 +33,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Effects
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
provider.RunRectangleConstrainedValidatingProcessorTest( provider.RunRectangleConstrainedValidatingProcessorTest(
(x, rect) => x.BackgroundColor(NamedColors<TPixel>.HotPink, rect)); (x, rect) => x.BackgroundColor(Color.HotPink, rect));
} }
} }
} }

6
tests/ImageSharp.Tests/Processing/Processors/Overlays/GlowTest.cs

@ -13,11 +13,11 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Overlays
[GroupOutput("Overlays")] [GroupOutput("Overlays")]
public class GlowTest : OverlayTestBase public class GlowTest : OverlayTestBase
{ {
protected override void Apply<T>(IImageProcessingContext<T> ctx, T color) => ctx.Glow(color); protected override void Apply(IImageProcessingContext ctx, Color color) => ctx.Glow(color);
protected override void Apply<T>(IImageProcessingContext<T> ctx, float radiusX, float radiusY) => protected override void Apply(IImageProcessingContext ctx, float radiusX, float radiusY) =>
ctx.Glow(radiusX); ctx.Glow(radiusX);
protected override void Apply<T>(IImageProcessingContext<T> ctx, Rectangle rect) => ctx.Glow(rect); protected override void Apply(IImageProcessingContext ctx, Rectangle rect) => ctx.Glow(rect);
} }
} }

13
tests/ImageSharp.Tests/Processing/Processors/Overlays/OverlayTestBase.cs

@ -27,8 +27,8 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Overlays
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
provider.Utility.TestGroupName = this.GetType().Name; provider.Utility.TestGroupName = this.GetType().Name;
var f = (FieldInfo)typeof(NamedColors<TPixel>).GetMember(colorName)[0]; var f = (FieldInfo)typeof(Color).GetMember(colorName)[0];
TPixel color = (TPixel)f.GetValue(null); Color color = (Color)f.GetValue(null);
provider.RunValidatingProcessorTest(x => this.Apply(x, color), colorName, ValidatorComparer, appendPixelTypeToFileName: false); provider.RunValidatingProcessorTest(x => this.Apply(x, color), colorName, ValidatorComparer, appendPixelTypeToFileName: false);
} }
@ -58,13 +58,10 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Overlays
provider.RunRectangleConstrainedValidatingProcessorTest((x, rect) => this.Apply(x, rect)); provider.RunRectangleConstrainedValidatingProcessorTest((x, rect) => this.Apply(x, rect));
} }
protected abstract void Apply<T>(IImageProcessingContext<T> ctx, T color) protected abstract void Apply(IImageProcessingContext ctx, Color color);
where T : struct, IPixel<T>;
protected abstract void Apply<T>(IImageProcessingContext<T> ctx, float radiusX, float radiusY) protected abstract void Apply(IImageProcessingContext ctx, float radiusX, float radiusY);
where T : struct, IPixel<T>;
protected abstract void Apply<T>(IImageProcessingContext<T> ctx, Rectangle rect) protected abstract void Apply(IImageProcessingContext ctx, Rectangle rect);
where T : struct, IPixel<T>;
} }
} }

6
tests/ImageSharp.Tests/Processing/Processors/Overlays/VignetteTest.cs

@ -9,11 +9,11 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Overlays
[GroupOutput("Overlays")] [GroupOutput("Overlays")]
public class VignetteTest : OverlayTestBase public class VignetteTest : OverlayTestBase
{ {
protected override void Apply<T>(IImageProcessingContext<T> ctx, T color) => ctx.Vignette(color); protected override void Apply(IImageProcessingContext ctx, Color color) => ctx.Vignette(color);
protected override void Apply<T>(IImageProcessingContext<T> ctx, float radiusX, float radiusY) => protected override void Apply(IImageProcessingContext ctx, float radiusX, float radiusY) =>
ctx.Vignette(radiusX, radiusY); ctx.Vignette(radiusX, radiusY);
protected override void Apply<T>(IImageProcessingContext<T> ctx, Rectangle rect) => ctx.Vignette(rect); protected override void Apply(IImageProcessingContext ctx, Rectangle rect) => ctx.Vignette(rect);
} }
} }
Loading…
Cancel
Save