Browse Source

Merge pull request #1000 from ip75/LightnessProcessor

image lightness filter
pull/1020/head
James Jackson-South 6 years ago
committed by GitHub
parent
commit
f4fecd5a15
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 44
      src/ImageSharp/Processing/Extensions/LightnessExtensions.cs
  2. 26
      src/ImageSharp/Processing/KnownFilterMatrices.cs
  3. 30
      src/ImageSharp/Processing/Processors/Filters/LightnessProcessor.cs
  4. 30
      tests/ImageSharp.Tests/Processing/Filters/LightnessTest.cs
  5. 30
      tests/ImageSharp.Tests/Processing/Processors/Filters/LightnessTest.cs
  6. 2
      tests/Images/External

44
src/ImageSharp/Processing/Extensions/LightnessExtensions.cs

@ -0,0 +1,44 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.Processing.Processors.Filters;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Processing
{
/// <summary>
/// Defines extensions that allow the alteration of the lightness component of an <see cref="Image"/>
/// using Mutate/Clone.
/// </summary>
public static class LightnessExtensions
{
/// <summary>
/// Alters the lightness component of the image.
/// </summary>
/// <remarks>
/// A value of 0 will create an image that is completely black. A value of 1 leaves the input unchanged.
/// Other values are linear multipliers on the effect. Values of an amount over 1 are allowed, providing lighter results.
/// </remarks>
/// <param name="source">The image this method extends.</param>
/// <param name="amount">The proportion of the conversion. Must be greater than or equal to 0.</param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
public static IImageProcessingContext Lightness(this IImageProcessingContext source, float amount)
=> source.ApplyProcessor(new LightnessProcessor(amount));
/// <summary>
/// Alters the lightness component of the image.
/// </summary>
/// <remarks>
/// A value of 0 will create an image that is completely black. A value of 1 leaves the input unchanged.
/// Other values are linear multipliers on the effect. Values of an amount over 1 are allowed, providing lighter results.
/// </remarks>
/// <param name="source">The image this method extends.</param>
/// <param name="amount">The proportion of the conversion. Must be greater than or equal to 0.</param>
/// <param name="rectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
/// </param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
public static IImageProcessingContext Lightness(this IImageProcessingContext source, float amount, Rectangle rectangle)
=> source.ApplyProcessor(new LightnessProcessor(amount), rectangle);
}
}

26
src/ImageSharp/Processing/KnownFilterMatrices.cs

@ -432,6 +432,32 @@ namespace SixLabors.ImageSharp.Processing
return m;
}
/// <summary>
/// Create a lightness filter matrix using the given amount.
/// </summary>
/// <remarks>
/// A value of 0 will create an image that is completely black. A value of 1 leaves the input unchanged.
/// Other values are linear multipliers on the effect. Values of an amount over 1 are allowed, providing lighter results.
/// </remarks>
/// <param name="amount">The proportion of the conversion. Must be greater than or equal to 0.</param>
/// <returns>The <see cref="ColorMatrix"/></returns>
public static ColorMatrix CreateLightnessFilter(float amount)
{
Guard.MustBeGreaterThanOrEqualTo(amount, 0, nameof(amount));
amount--;
return new ColorMatrix
{
M11 = 1F,
M22 = 1F,
M33 = 1F,
M44 = 1F,
M51 = amount,
M52 = amount,
M53 = amount
};
}
/// <summary>
/// Create a sepia filter matrix using the given amount.
/// The formula used matches the svg specification. <see href="http://www.w3.org/TR/filter-effects/#sepiaEquivalent"/>

30
src/ImageSharp/Processing/Processors/Filters/LightnessProcessor.cs

@ -0,0 +1,30 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
namespace SixLabors.ImageSharp.Processing.Processors.Filters
{
/// <summary>
/// Applies a lightness filter matrix using the given amount.
/// </summary>
public sealed class LightnessProcessor : FilterProcessor
{
/// <summary>
/// Initializes a new instance of the <see cref="LightnessProcessor"/> class.
/// </summary>
/// <remarks>
/// A value of <value>0</value> will create an image that is completely black. A value of <value>1</value> leaves the input unchanged.
/// Other values are linear multipliers on the effect. Values of an amount over 1 are allowed, providing lighter results.
/// </remarks>
/// <param name="amount">The proportion of the conversion. Must be greater than or equal to 0.</param>
public LightnessProcessor(float amount)
: base(KnownFilterMatrices.CreateLightnessFilter(amount))
{
this.Amount = amount;
}
/// <summary>
/// Gets the proportion of the conversion
/// </summary>
public float Amount { get; }
}
}

30
tests/ImageSharp.Tests/Processing/Filters/LightnessTest.cs

@ -0,0 +1,30 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Processing.Processors.Filters;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Processing.Effects
{
public class LightnessTest : BaseImageOperationsExtensionTest
{
[Fact]
public void Lightness_amount_LightnessProcessorDefaultsSet()
{
this.operations.Lightness(.5F);
LightnessProcessor processor = this.Verify<LightnessProcessor>();
Assert.Equal(.5F, processor.Amount);
}
[Fact]
public void Lightness_amount_rect_LightnessProcessorDefaultsSet()
{
this.operations.Lightness(.5F, this.rect);
LightnessProcessor processor = this.Verify<LightnessProcessor>(this.rect);
Assert.Equal(.5F, processor.Amount);
}
}
}

30
tests/ImageSharp.Tests/Processing/Processors/Filters/LightnessTest.cs

@ -0,0 +1,30 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.PixelFormats;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Effects
{
using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison;
[GroupOutput("Filters")]
public class LightnessTest
{
private readonly ImageComparer imageComparer = ImageComparer.Tolerant(0.007F);
public static readonly TheoryData<float> LightnessValues
= new TheoryData<float>
{
.5F,
1.5F
};
[Theory]
[WithTestPatternImages(nameof(LightnessValues), 48, 48, PixelTypes.Rgba32)]
public void ApplyLightnessFilter<TPixel>(TestImageProvider<TPixel> provider, float value)
where TPixel : struct, IPixel<TPixel> => provider.RunValidatingProcessorTest(ctx => ctx.Lightness(value), value, this.imageComparer);
}
}

2
tests/Images/External

@ -1 +1 @@
Subproject commit 468e39ad25c9c2f38d5a16d603ec09f11d1fe0a2
Subproject commit 58b2c01f9b66dd42d2b5b040b85e6846083b5e5f
Loading…
Cancel
Save