diff --git a/src/ImageProcessor/Filters/Brightness.cs b/src/ImageProcessor/Filters/Brightness.cs
new file mode 100644
index 0000000000..5edd4963fa
--- /dev/null
+++ b/src/ImageProcessor/Filters/Brightness.cs
@@ -0,0 +1,77 @@
+//
+// Copyright (c) James South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageProcessor.Filters
+{
+ using System;
+ using System.Numerics;
+ using System.Threading.Tasks;
+
+ ///
+ /// An to change the brightness of an .
+ ///
+ public class Brightness : ParallelImageProcessor
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The new brightness of the image. Must be between -100 and 100.
+ ///
+ /// is less than -100 or is greater than 100.
+ ///
+ public Brightness(int brightness)
+ {
+ Guard.MustBeBetweenOrEqualTo(brightness, -100, 100, nameof(brightness));
+ this.Value = brightness;
+ }
+
+ ///
+ /// Gets the brightness value.
+ ///
+ public int Value { get; }
+
+ ///
+ protected override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
+ {
+ float brightness = this.Value / 100f;
+ int sourceY = sourceRectangle.Y;
+ int sourceBottom = sourceRectangle.Bottom;
+ int startX = sourceRectangle.X;
+ int endX = sourceRectangle.Right;
+
+ Parallel.For(
+ startY,
+ endY,
+ y =>
+ {
+ if (y >= sourceY && y < sourceBottom)
+ {
+ for (int x = startX; x < endX; x++)
+ {
+ target[x, y] = AdjustBrightness(source[x, y], brightness);
+ }
+ }
+ });
+ }
+
+ ///
+ /// Returns a with the brightness adjusted.
+ ///
+ /// The source color.
+ /// The brightness adjustment factor.
+ ///
+ /// The .
+ ///
+ private static Color AdjustBrightness(Color color, float brightness)
+ {
+ color = PixelOperations.ToLinear(color);
+
+ Vector3 vector3 = color.ToVector3();
+ vector3 += new Vector3(brightness, brightness, brightness);
+
+ return PixelOperations.ToSrgb(new Color(vector3, color.A));
+ }
+ }
+}
diff --git a/src/ImageProcessor/Filters/ColorMatrix/ColorMatrix.cs b/src/ImageProcessor/Filters/ColorMatrix/ColorMatrix.cs
index 6885acc070..0cab8e1ef6 100644
--- a/src/ImageProcessor/Filters/ColorMatrix/ColorMatrix.cs
+++ b/src/ImageProcessor/Filters/ColorMatrix/ColorMatrix.cs
@@ -8,7 +8,7 @@
namespace ImageProcessor.Filters
{
///
- /// Defines a 5 x 5 matrix that contains the coordinates for the RGBAW color space.
+ /// Defines a 5x5 matrix that contains the coordinates for the RGBAW color space.
///
public sealed class ColorMatrix
{
diff --git a/src/ImageProcessor/Filters/Contrast.cs b/src/ImageProcessor/Filters/Contrast.cs
index 0986dc3d0f..50d45d397b 100644
--- a/src/ImageProcessor/Filters/Contrast.cs
+++ b/src/ImageProcessor/Filters/Contrast.cs
@@ -67,6 +67,7 @@ namespace ImageProcessor.Filters
{
color = PixelOperations.ToLinear(color);
+ // Seems to be faster than Vector3.
color.R -= 0.5f;
color.R *= contrast;
color.R += 0.5f;
diff --git a/src/ImageProcessor/Filters/Saturation.cs b/src/ImageProcessor/Filters/Saturation.cs
new file mode 100644
index 0000000000..7167d6d00e
--- /dev/null
+++ b/src/ImageProcessor/Filters/Saturation.cs
@@ -0,0 +1,78 @@
+//
+// Copyright (c) James South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageProcessor.Filters
+{
+ using System;
+ using System.Numerics;
+ using System.Threading.Tasks;
+
+ ///
+ /// An to change the saturation of an .
+ ///
+ public class Saturation : ParallelImageProcessor
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The new saturation of the image. Must be between -100 and 100.
+ ///
+ /// is less than -100 or is greater than 100.
+ ///
+ public Saturation(int saturation)
+ {
+ Guard.MustBeBetweenOrEqualTo(saturation, -100, 100, nameof(saturation));
+ this.Value = saturation;
+ }
+
+ ///
+ /// Gets the saturation value.
+ ///
+ public int Value { get; }
+
+ ///
+ protected override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
+ {
+ float saturation = this.Value / 100f;
+ int sourceY = sourceRectangle.Y;
+ int sourceBottom = sourceRectangle.Bottom;
+ int startX = sourceRectangle.X;
+ int endX = sourceRectangle.Right;
+
+ Parallel.For(
+ startY,
+ endY,
+ y =>
+ {
+ if (y >= sourceY && y < sourceBottom)
+ {
+ for (int x = startX; x < endX; x++)
+ {
+ target[x, y] = AdjustSaturation(source[x, y], saturation);
+ }
+ }
+ });
+ }
+
+ ///
+ /// Returns a with the saturation adjusted.
+ ///
+ /// The source color.
+ /// The saturation adjustment factor.
+ ///
+ /// The .
+ ///
+ private static Color AdjustSaturation(Color color, float saturation)
+ {
+ //color = PixelOperations.ToLinear(color);
+
+ // TODO: This can be done with a matrix. But why can I not get conversion to work?
+ Hsv hsv = color;
+ return new Hsv(hsv.H, saturation, hsv.V);
+
+ //return PixelOperations.ToSrgb(newHsv);
+ }
+ }
+}
diff --git a/src/ImageProcessor/ImageProcessor.csproj b/src/ImageProcessor/ImageProcessor.csproj
index 48294d14f7..fdb70a1833 100644
--- a/src/ImageProcessor/ImageProcessor.csproj
+++ b/src/ImageProcessor/ImageProcessor.csproj
@@ -48,6 +48,9 @@
+
+
+
diff --git a/tests/ImageProcessor.Tests/Processors/Filters/FilterTests.cs b/tests/ImageProcessor.Tests/Processors/Filters/FilterTests.cs
index e1fe80d01d..ace61db0db 100644
--- a/tests/ImageProcessor.Tests/Processors/Filters/FilterTests.cs
+++ b/tests/ImageProcessor.Tests/Processors/Filters/FilterTests.cs
@@ -12,16 +12,20 @@ namespace ImageProcessor.Tests
{
public static readonly TheoryData Filters = new TheoryData
{
+ //{ "Brightness-50", new Brightness(50) },
+ //{ "Brightness--50", new Brightness(-50) },
//{ "Contrast-50", new Contrast(50) },
//{ "Contrast--50", new Contrast(-50) },
+ { "Saturation-100", new Saturation(100) },
+ { "Saturation--0", new Saturation(0) },
//{ "Alpha--50", new Alpha(50) },
- { "Invert", new Invert() },
- { "Sepia", new Sepia() },
- { "BlackWhite", new BlackWhite() },
- { "Lomograph", new Lomograph() },
- { "Polaroid", new Polaroid() },
- { "GreyscaleBt709", new GreyscaleBt709() },
- { "GreyscaleBt601", new GreyscaleBt601() },
+ //{ "Invert", new Invert() },
+ //{ "Sepia", new Sepia() },
+ //{ "BlackWhite", new BlackWhite() },
+ //{ "Lomograph", new Lomograph() },
+ //{ "Polaroid", new Polaroid() },
+ //{ "GreyscaleBt709", new GreyscaleBt709() },
+ //{ "GreyscaleBt601", new GreyscaleBt601() },
};
[Theory]